list to currying
От: sirGrey Беларусь  
Дата: 04.06.07 15:36
Оценка:
Привет!

Знает ли кто нибудь как передать список в качестве параметров обычной (curryied) функции в Caml?
Примерно так:
let apply_list f list = ...
let sum = apply_list (+) [1; 2]

Начал понемногу разбираться с OCaml и стали появляться "глупые вопросы"
Задачка возникла во время распития чая на даче, после дня физических упражнений
Первоначально захотел реализовать Лиспообразный map: берущий функцию и список списков и возвращающий список.
Другими словами
map f [[x1; x2; ...]; [y1; y2; ...]; ...] -> [(f x1 y1 ...); (f x2 y2 ...); ...]

Упёрся в первую функцию — если её написать то задача решается
Ясно что транспонировав список списков или используя список кортежей/записей задача решается элементарно.
Вопрос в ограничениях синтаксиса языка.

--
Yami ga watashi to issyoni iku.
Re: list to currying
От: geniepro http://geniepro.livejournal.com/
Дата: 04.06.07 19:26
Оценка:
Здравствуйте, sirGrey, Вы писали:

В принципе, такое можно, но будет очень громоздко, потому что мешает статическая типизация.

Если не возражаете, покажу пример на Хаскелле. С небольшими переделками его можно и на Окамле реализовать (думаю, это не трудно, просто я в Камлях так и не разобрался из-за Хаскелла

Если пытаться напрямую реализовать это применение, то мы упрёмся в такой вариант:
f3 a b c = a + b * c

eval1 f [a]       = f a
eval2 f [a, b]    = f a b
eval3 f [a, b, c] = f a b c       -- и т.д.

main = do 
    print $ eval1 (1+) [1]        -- 2
    print $ eval2  (+) [1, 2]     -- 3
    print $ eval3  f3  [1, 2, 3]  -- 7

Как видите, мы вынуждены создать разные применители (evalx) для функций f с разной арностью.
Можно воспользоваться алгебраическими типами данных и получить полиморфный вариант:
f3 a b c = a + b * c

data Eval a b = Eval1 (a -> b)
              | Eval2 (a -> a -> b)
              | Eval3 (a -> a -> a -> b)  -- и т.д.

eval (Eval1 f) [a]       = f a
eval (Eval2 f) [a, b]    = f a b
eval (Eval3 f) [a, b, c] = f a b c        -- и т.д.

main = do 
    print $ eval  (Eval1 (1+)) [1]        -- 2
    print $ eval  (Eval2  (+)) [1, 2]     -- 3
    print $ eval  (Eval3  f3 ) [1, 2, 3]  -- 7

Естественно, нужно ещё как-то проследить, что бы в списке было ровно столько элементов, сколько аргументов у применяемой к ним функции f...
Re: list to currying
От: deniok Россия  
Дата: 04.06.07 20:09
Оценка:
Здравствуйте, sirGrey, Вы писали:

G>Знает ли кто нибудь как передать список в качестве параметров обычной (curryied) функции в Caml?

G>Примерно так:
G>let apply_list f list = ...
G>let sum = apply_list (+) [1; 2]

В общем виде это невозможно. Я в своё время размышлял над этим, и пришёл к выводу, что функции неопределённой арности, разрушая систему типов Хиндли-Милнера, ничего особо хорошего взамен не дают. То есть диспатч по каждой следующей арности надо делать ручками, и это правильно
Re: list to currying
От: lomeo Россия http://lomeo.livejournal.com/
Дата: 05.06.07 11:46
Оценка:
Здравствуйте, sirGrey, Вы писали:

G>Начал понемногу разбираться с OCaml и стали появляться "глупые вопросы"

G>Задачка возникла во время распития чая на даче, после дня физических упражнений
G>Первоначально захотел реализовать Лиспообразный map: берущий функцию и список списков и возвращающий список.
G>Другими словами
G>map f [[x1; x2; ...]; [y1; y2; ...]; ...] -> [(f x1 y1 ...); (f x2 y2 ...); ...]

На Хаскеле есть семейство функций zipWithN для этой задачи. Сделать список списков — это не лисповый map,
т.к. список списков — имеет тип [a]], а в лиспе что то вроде [a],[b],[c]...]
Если не привязываться именно к списку списков, но постараться универсально сделать подобную лиспу функцию,
то есть один приём для твоей задачи. Могу нарисовать на Хаскеле, наверняка на Окамле будет несложнее:

(<<) :: [a -> b] -> [a] -> [b]
(f:fs) << (x:xs) = f x : (fs << xs)
_      << _      = []

-- и дальше
map f xs1 << xs2 << xs3


Разумеется, в отличие от лиспа здесь придётся заранее знать кол-во "столбцов"
Собственно, это кол-во определяется типом функции f :: a -> b -> c -> .. -> r
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: list to currying
От: BulatZiganshin  
Дата: 05.06.07 11:56
Оценка: +1
G>Вопрос в ограничениях синтаксиса языка.

вопрос в строгой типизации. надо перестраивать мышление от динамических языков к статическим. судя по твоим темам, ты борешься не с теми демонами
Люди, я люблю вас! Будьте бдительны!!!
Re[2]: list to currying
От: sirGrey Беларусь  
Дата: 05.06.07 16:03
Оценка:
Здравствуйте, BulatZiganshin, Вы писали:

G>>Вопрос в ограничениях синтаксиса языка.


BZ>вопрос в строгой типизации. надо перестраивать мышление от динамических языков к статическим. судя по твоим темам, ты борешься не с теми демонами


Я не борюсь — я читаю SICP, знакомлюсь с OCaml и программирую на Java (Swing + EJB + custom DAO + Oracle).

Данный вопрос — это вообще-то "idle curiosity"
Интересно можно ли токое сделать — хотя бы чисто теоритически.
Интуитивно чуйствую что используя бесконечные рекурсивные типы — можно, но для более рационального рассуждения математической базы всё-таки не хватает
--
Beatus vir qui suffert tentationem,
Quoniam cum probatus fuerit
Accipiet coronam vitae,
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.