我刚刚读完《Learn You A Haskell For Great Good》的第 11 章,我想在继续之前更好地了解 Applicative Functor。我有以下 ghci 代码。
let a = Just (5+) -- Instead of mapping + to Just 5
let b = (3+) <$> a -- I imported Control.Applicative even though most of these modules are deprecated
let c = Just (3+) <*> a -- I expect this to be equivalent to b and :t b, :t c shows that they are the 'same'
a <*> Just 1 -- returns 6 as I expected
现在我期望 b 和 c 为:Just ((3+) . (5+)) 这意味着我可以这样做:
b <*> Just 1 -- and get 9 as in (3+) $ (5+) 1 or ((3+) . (5+)) 1
但是我得到:在交互式 GHCI 命令的 stmt 中使用“it”而没有出现 (Num (b0 -> b0)) 的实例:打印它。
问题 1:如下所示的限制意味着什么:
b :: (Num (a -> a), Num a) => Maybe (a -> a)
我认为这只是意味着 <*> 可以从“b”中“提取”(a -> a)。在我的菜鸟头脑中,我知道 Num a 意味着 'a' 必须是 Num 的实例,但 Num (a -> a) 对我来说没有多大意义。这是否意味着 Maybe 内的 (a -> b) 必须返回 Num 的实例?
问题 2:我所做的一切在应用领域不是可行的吗?有没有任何明显的方法可以打印或查看 'b <*> Just 1' 的结果?
let Just val = b <*> Just 1
:t val -- returns ((Num (t -> t), Num t) => t which tells me that val is an instance of Num but then again I am just a beginner so what do I know?
注意:我有 ghci session 的快照,如有必要可以添加它们。我读了一些相关的帖子,但似乎没有什么能启发我。
最佳答案
当你写作时(展开)
let b = (3+) <$> Just (5+)
结果值,根据 <$>
的定义(就是fmap
!)是:
Just (3 + (5+))
您正在向函数添加一个数字!这就是为什么你会遇到奇怪的类型错误。
具体来说,Haskell 正在拼命地假装 (5+)
是一个数字:
b :: (Num (a -> a), Num a) => Maybe (a -> a)
它的意思是,如果有某种疯狂的类型 a
其中a
和(a -> a)
都是 Num
的实例,我可以在 Functor 中将它们加在一起,就好像它们是数字一样,并给出结果 Maybe (a -> a)
! 但是,一般来说,函数不是 Num
的实例。 typeclass,所以一切都会爆炸。
你的意思是写:
let b = ((3+).) <$> Just (5+)
这确实如您所期望的那样工作( b <*> Just 1 == Just 9
)。
关于haskell - 尝试更好地理解 Haskell 中应用仿函数的 (<*>) 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31725525/