Haskell: Составить функцию определенного типа с функцией общего типа? - PullRequest
1 голос
/ 31 декабря 2011

Я писал быстрый однострочный текст в GHCi и пытался составить сумму с картой. Я понял причину, по которой это не удалось, потому что карта дает выходные данные общего типа [b], тогда как сумма принимает конкретные входные данные Num a => [a]. Однако в этом коде нет ничего плохого, если предположить, что вывод функции map имеет тип Num b => [b].

Я думал, что написание ограничивающего объявления типа может сработать (хотя я полагаю, что это мешает вам делать это в GHCi), но все равно этого не произошло:

myFunc :: Num b => (a -> b) -> [a] -> b
myFunc = sum . map

дал мне следующую ошибку:

Couldn't match expected type `[[a] -> b]'
            with actual type `[a] -> [b]'
Expected type: (a -> b) -> [[a] -> b]
  Actual type: (a -> b) -> [a] -> [b]
In the second argument of `(.)', namely `map'
In the expression: sum . map

Есть ли способ сделать это? Может быть, я просто упускаю что-то очевидное (новое для Хаскелла).

1 Ответ

5 голосов
/ 31 декабря 2011

sum . map не определение, которое вы ищете. Обратите внимание, что

 (.) :: (b -> c) -> (a -> b) -> a -> c

Оператор точки принимает две унарные функции. Он не работает, так как map принимает два аргумента:

map :: (a -> b) -> [a] -> [b]

Одним из возможных решений было бы явное связывание первого аргумента map:

myFunc :: Num c => (a -> c) -> [a] -> c
myFucc f = sum . map f

В качестве альтернативы вы можете использовать curry и uncurry и достичь того же результата.

myFunc = curry $ sum . uncurry map
...