Haskell: скомпоновать функцию определенного типа с функцией общего типа?

Я быстро написал однострочник в GHCI и попытался составить сумму с картой. Я решил, что причина, по которой это не удалось, заключается в том, что карта дает вывод общего типа [b], тогда как сумма принимает конкретный ввод Num a => [a]. Однако в этом коде нет ничего плохого, если предположить, что вывод функции карты имеет тип 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

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


person alkjiughh17652    schedule 31.12.2011    source источник
comment
Попробуйте myFunc f = sum . map f. (.) составляет унарные функции.   -  person Thomas Eding    schedule 31.12.2011


Ответы (1)


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
person Jan    schedule 31.12.2011
comment
Другое безточечное определение: (sum .) . map или sum .: map, где (.:) = (.) . (.). - person Jon Purdy; 31.12.2011
comment
Оператор точки принимает две унарные функции. Это не работает ... Ну, технически все функции являются унарными функциями; функции с несколькими аргументами — это просто унарные функции, которые возвращают другие функции. Так что это не работает, потому что карта принимает два аргумента; это просто работает иначе, чем предполагалось OP - person newacct; 01.01.2012