简体   繁体   English

Haskell代码如何工作? fmap fmap(,)<*>刚刚。 相反

[英]How does this Haskell code work? fmap fmap (,) <*> Just . reverse

Would someone help explain/breakdown the following code: 有人会帮助解释/分解以下代码:

λ> fmap fmap (,) <*> Just . reverse $ "stackoverflow"
Just ("stackoverflow","wolfrevokcats")

It would be great if someone could walk me through their process of understanding the mechanics of this kind of code. 如果有人可以引导我完成他们理解这种代码的原理的过程,那就太好了。

Let's try to decode this pointless style obfuscation: 让我们尝试解码这种毫无意义的样式混淆:

fmap fmap (,) <*> Just . reverse $ "stackoverflow"

First step: how this is parsed? 第一步:如何解析? Well, $ has low precedence, so it's 好吧, $优先级较低,因此

(fmap fmap (,) <*> Just . reverse) $ "stackoverflow"

Also, I guess that the infix <*> has a lower precedence than . 另外,我猜中缀<*>的优先级低于. (one could check using the documentation or :i in GHCi). (可以使用GHCi中的文档或:i进行检查)。 So, we get 所以,我们得到

((fmap fmap (,)) <*> (Just . reverse)) $ "stackoverflow"

Let's beta-reduce the $ 让我们Beta减少$

((fmap fmap (,)) <*> (Just . reverse)) "stackoverflow"

So, the result of <*> is a function. 因此, <*>的结果是一个函数。 This means that we are working in the (->) a applicative. 这意味着我们正在使用(->) a应用程序。 There, (<*>) = \\xyz -> xz (yz) AKA the S combinator from lambda calculus. 那里, (<*>) = \\xyz -> xz (yz)又名Lambda演算的S组合器。 We can beta-reduce that: 我们可以beta减少:

(\z -> (fmap fmap (,)) z ((Just . reverse) z)) "stackoverflow"

More betas, removing parentheses when we can: 更多beta,可以删除括号:

fmap fmap (,) "stackoverflow" ((Just . reverse) "stackoverflow")

More simplification: 更简化:

fmap fmap (,) "stackoverflow" (Just (reverse "stackoverflow"))
fmap fmap (,) "stackoverflow" (Just "wolfrevokcats")

Now, the fmap fmap (,) part. 现在, fmap fmap (,)部分。 The (,) argument is a function, so this means that the first fmap is working in the (->) a functor. (,)参数是一个函数,因此这意味着第一个fmap(->) a函数中起作用。 There, fmap = (.) . 在那里, fmap = (.) So, it's just obfuscation for 所以,这只是对

(.) fmap (,) "stackoverflow" (Just "wolfrevokcats")
(fmap . (,)) "stackoverflow" (Just "wolfrevokcats")
(fmap ((,) "stackoverflow")) (Just "wolfrevokcats")
fmap ((,) "stackoverflow") (Just "wolfrevokcats")

Now, the second argument of fmap is of type Maybe String , so the fmap is working in the Maybe functor. 现在, fmap的第二个参数的类型为Maybe String ,因此fmapMaybe函数中起作用。 There, fmap f (Just x) = Just (fx) . 在那里, fmap f (Just x) = Just (fx) We get 我们得到

Just (((,) "stackoverflow") "wolfrevokcats")
Just ((,) "stackoverflow" "wolfrevokcats")
Just ("stackoverflow", "wolfrevokcats")

Conclusion: pointless code is often pointless. 结论:毫无意义的代码通常是毫无意义的。 To decode this snippet we had to run the type inferer in our head, recall three specific instances (even if they are pretty standard), and cope with precedence. 要解码此代码段,我们必须在头上运行类型推断器,重新调用三个特定的实例(即使它们是非常标准的),并应对优先级。 No one should ever use this style except for deliberate obfuscation. 除了故意混淆之外,没有人可以使用这种样式。 (Surely not as a hiring puzzle!) (当然不是招聘难题!)

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

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