haskell - 尝试更好地理解 Haskell 中应用仿函数的 (<*>) 函数

标签 haskell

我刚刚读完《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/

相关文章:

GHCi 中的 Haskell csv 管道

haskell - 无法为 Continuation Monad Transformer 派生 MonadWriter 的实例?

haskell - 如何从 GHCi 中启用语言扩展?

Haskell中函数调用的优化

haskell - 如何将外部导出函数的参数传递到管道中?

haskell - 如何在 Haskell 中编写事件总线?

haskell - 是否可以在 Haskell 中分析空间使用情况

haskell - 在负输入 Haskell 上崩溃

haskell - 如何将函数映射到列表并在满足条件时停止并告诉我它是停止还是到达末尾?

list - 如何通过列表理解计算频率?