Как заставить Haskell распознавать функции как аппликативные функторы - PullRequest
2 голосов
/ 10 апреля 2020

Я новичок в Haskell и до сих пор не понимаю, как обращаться с их системой типов. Моя проблема в том, что я играю с функцией sequenceA из книги Learn You a Haskell For Great Good . Вот функция:

sequenceA :: (Applicative f) => [f a] -> f [a]
sequenceA = foldr (liftA2 (:)) (pure [])

Я пытался адаптировать ее для конкретного использования c, поэтому я написал следующую функцию:

binner :: Int -> [Int -> Int]
binner n = (map (\x -> bin x) [n, (n-1) .. 1])
  where bin n = (`mod` 2) . (`div` 2^(n-1))

У меня нет проблем с использованием этих функций отдельно , Например, в GHCi прекрасно работает следующее:

sequenceA (binner 4) 10

Если я наберу следующее в GHCi,

:t (sequenceA (binner 4))

Это будет выглядеть следующим образом:

(sequenceA (binner 4)) :: Int -> [Int]

Однако я не могу понять, как объединить функции. Интуитивно кажется, что я должен быть в состоянии сделать следующее, используя тот же тип, который показал GHCi:

binner :: Int -> [Int]
binner n = foldr (liftA2 (:)) (pure []) $ (map (\x -> bin x) [n, (n-1) .. 1])
  where bin n = (`mod` 2) . (`div` 2^(n-1))

Но это приводит к ошибке компиляции:

Не удалось сопоставить type '[a0]' with 'Int' Ожидаемый тип: [Int] Фактический тип: [[a0]]

Я пытался связываться с объявлением типа, но не понял, как исправить Это.

Спасибо за помощь!

1 Ответ

3 голосов
/ 10 апреля 2020

Вы пытались использовать тип sequenceA (binner 4) с телом по существу \n -> sequenceA (binner n). Так как то, что вы написали, принимает Int, а не то, что вы дали :t, вам нужно добавить Int -> в начало сигнатуры типа, чтобы представить n:

binner :: Int -> Int -> [Int]
binner n = foldr (liftA2 (:)) (pure []) $ (map (\x -> bin x) [n, (n-1) .. 1])
  where bin n = (`mod` 2) . (`div` 2^(n-1))

Вместо этого вы можете сохранить тип, но жестко закодировать 4:

binner :: Int -> [Int]
binner = foldr (liftA2 (:)) (pure []) $ (map (\x -> bin x) [4, (4-1) .. 1])
  where bin n = (`mod` 2) . (`div` 2^(n-1))
...