简体   繁体   English

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

[英]How to get Haskell to recognize functions as applicative functors

I'm new to Haskell and still don't understand how to deal with their type system.我是 Haskell 的新手,仍然不明白如何处理他们的类型系统。 My problem is that I'm playing around with the sequenceA function from the book Learn You a Haskell For Great Good .我的问题是我正在玩《 Learn You a Haskell For Great Good 》一书中的序列A function 。 Here's the function:这是 function:

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

I tried to adapt it to a specific use, so I wrote the following function:我试图让它适应特定的用途,所以我写了以下 function:

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

I have no problem using these functions separately.单独使用这些功能没有问题。 For example, the following works great in GHCi:例如,以下在 GHCi 中效果很好:

sequenceA (binner 4) 10

If I type the following in GHCi,如果我在 GHCi 中键入以下内容,

:t (sequenceA (binner 4))

It shows the type as:它显示类型为:

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

However, I can't figure out how to combine the functions.但是,我不知道如何组合这些功能。 Intuitively, it seems I should be able to do the following, using the same type that GHCi showed:直觉上,似乎我应该能够使用 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))

But that throws an error compiling:但这会引发编译错误:

Couldn't match type '[a0]' with 'Int' Expected type: [Int] Actual type: [[a0]]无法将类型“[a0]”与“Int”匹配预期类型:[Int] 实际类型:[[a0]]

I tried messing with the type declaration, but haven't figured out how to fix it.我尝试弄乱类型声明,但还没有弄清楚如何解决它。

Thanks for the help!谢谢您的帮助!

You tried to use the type of sequenceA (binner 4) with the body of essentially \n -> sequenceA (binner n) .您尝试将sequenceA (binner 4)的类型与基本上\n -> sequenceA (binner n)的主体一起使用。 Since what you wrote takes an Int that what you gave to :t doesn't, you need to add an Int -> to the beginning of the type signature to represent the 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))

You could instead keep the type, but hardcode the 4:您可以改为保留类型,但对 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))

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM