Это мои первые исследования в Haskell, поэтому простите меня, если это будет очевидно.
Я играл весь день с Haskell, просеивая через учебник 99 вопросов по HaskellWiki, используя мой собственный тип списка (типичный минус). Я добавил "очевидные" функции по мере того, как я продолжал, и я постарался сделать их максимально лаконичными (с использованием точечной нотации, когда это возможно)
12-я проблема заключается в декодировании кодированного списка длины, который:
> decode [Multiple 5 'a', Single 'b', Multiple 2 'c']
"aaaaabcc"
И я подумал об использовании map
для декодирования каждого элемента, затем concat
результата (спасибо Google на этом) и, наконец, вспомнил, что в своих чтениях я видел что-то вроде concatMap
, которое GHCi быстро подтвердило:
> :t map
map :: (a -> b) -> [a] -> [b]
> :t concat
concat :: [[a]] -> [a]
> :t concatMap
concatMap :: (a -> [b]) -> [a] -> [b]
Было похоже, что было бы переопределить concatMap
:
concatMap :: (a -> [b]) -> [a] -> [b]
concatMap = concat . map
За исключением того, что GHCi вполне жалуется:
List.hs:110:15:
Couldn't match expected type `[a] -> [b]'
with actual type `[a0]'
Expected type: [[a0]] -> [a] -> [b]
Actual type: [[a0]] -> [[a0]]
In the first argument of `(.)', namely `concat'
In the expression: concat . map
Я не мог понять это, поэтому я посмотрел в Интернете, и на самом деле определение, указанное в Prelude:
concatMap f = concat . map f
И я не совсем понимаю, почему это f необходимо, так как это тип, очевидно, a -> [b]
, как указано сигнатурой...
Итак, зачем здесь f
?