如何让 Haskell 将函数识别为应用函子

How to get Haskell to recognize functions as applicative functors

我是 Haskell 的新手,仍然不明白如何处理他们的类型系统。我的问题是我正在使用 sequenceA 一书中的函数 Learn You a Haskell For Great Good。这是函数:

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

我试图让它适应特定的用途,所以我写了以下函数:

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))

但这会引发编译错误:

Couldn't match type ‘[a0]’ with ‘Int’ Expected type: [Int] Actual type: [[a0]]

我试过弄乱类型声明,但还没有想出如何修复它。

感谢您的帮助!

您试图将 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))