这个Haskell代码如何工作? fmap fmap(,)< *>只是。相反

时间:2017-07-04 16:42:55

标签: haskell applicative

有人会帮助解释/细分以下代码:

0

如果有人能够指导我理解这种代码的机制,那将是很棒的。

1 个答案:

答案 0 :(得分:10)

让我们尝试解码这种毫无意义的样式混淆:

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

第一步:如何解析?好吧,$的优先级很低,所以它是

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

另外,我猜中缀<*>的优先级低于.(可以使用文档或GHCi中的:i进行检查)。所以,我们得到

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

让我们降低$

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

因此,<*>的结果是一个函数。这意味着我们正在使用(->) a应用程序。在那里,(<*>) = \x y z -> x z (y z) AKA是来自lambda演算的S组合子。我们可以通过beta减少:

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

更多测试版,在我们可以的时候删除括号:

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

更简化:

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

现在,fmap fmap (,)部分。 (,)参数是一个函数,因此这意味着第一个fmap正在(->) a仿函数中运行。那里,fmap = (.)。所以,这只是

的混淆
(.) fmap (,) "stackoverflow" (Just "wolfrevokcats")
(fmap . (,)) "stackoverflow" (Just "wolfrevokcats")
(fmap ((,) "stackoverflow")) (Just "wolfrevokcats")
fmap ((,) "stackoverflow") (Just "wolfrevokcats")

现在,fmap的第二个参数的类型为Maybe String,因此fmap正在Maybe仿函数中运行。那里,fmap f (Just x) = Just (f x)。我们得到

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

结论:无意义的代码往往毫无意义。要解码这个片段,我们必须在头脑中运行类型推理器,回忆三个特定实例(即使它们非常标准),并应对优先级。除了故意混淆之外,没有人应该使用这种风格。 (当然不是招聘谜题!)