Возможный дубликат:
Почему такое определение функции не разрешено в haskell?
Я новичок в мире Haskell, перейдя из Lisp. Я пытаюсь приспособиться к принципиально другому мировоззрению Haskell, и одна из многих вещей, которые я нахожу новыми и захватывающими, - это система типов. Будучи Lisper, я думал, что попытаюсь реализовать в Haskell функцию, которая очень важна в мире Lisp: apply
. Для тех, кто не знает, применяет функцию и список аргументов и вызывает функцию этих аргументов. В схеме (apply + '(1 2 3))
совпадает с вызовом (+ 1 2 3)
и возвращает 6.
Мой код Haskell выглядит примерно так:
apply x [] = x
apply f (x:xs) = apply (f x) xs
Но Хаскелл жалуется:
ERROR line 2 - Type error in function binding
*** Term : apply
*** Type : (b -> a) -> [b] -> a
*** Does not match : a -> [b] -> a
*** Because : unification would give infinite type
И я думаю, что я понимаю, почему. Тип Apply должен быть различным в зависимости от длины списка, который он задает. Учитывая список, скажем, 3-х элементов, тип apply должен быть: (a -> a -> a -> b) -> [a] -> b
, но при наличии списка из 6 элементов применить тип должен быть: (a -> a -> a -> a -> a -> a -> b) -> [a] -> b
.
Я пробовал эту ужасную работу:
data FnOrDat a b = Dat b | Fn (a -> FnOrDat a b)
apply :: (FnOrDat a b) -> [a] -> (FnOrDat a b)
apply x [] = x
apply (Fn f) (x:xs) = apply (f x) xs
apply (Dat _) _ = error "Cannot apply something which is not a function!"
add a = Fn (\b -> Dat (a + b))
main = putStrLn $ show $ x where Dat x = apply (Fn add) [5,1]
Это работает, но он вряд ли считается функцией apply
, потому что я не могу передать apply
нормальную функцию, я должен использовать ту, которая была написана специально для использования моей (неудобной) абстракции FnOrDat. Если бы я хотел написать функцию, которая добавила четыре числа, мне нужно было бы написать
add4 a = Fn (\b -> Fn (\c -> Fn (\d -> Dat (a + b + c + d))))
Еа.
Итак - я что-то упускаю или прошу об универсальном apply
в основном как просить функцию, которая может манипулировать кортежем произвольной длины? Имеет ли смысл apply
смысл в статически типизированном мировоззрении Haskell?