繁体   English   中英

当<*>中的函数为Nothing时,为什么Maybe的Nant的Applicative实例无效

[英]Why does the Applicative instance for Maybe give Nothing when function is Nothing in <*>

我是haskell的初学者,正在阅读“了解你是一本哈克尔书”。 我一直试图消化仿函数和应用函子一段时间。

在applicative functors主题中, Maybe的实例实现为

instance Applicative Maybe where
  pure = Just
  Nothing <*> _ = Nothing
  (Just f) <*> something = fmap f something

所以,我的理解是,我们得到了Nothing ,如果左侧仿函数(对于<*>是没有。 对我来说,似乎更有意义

  Nothing <*> something = something

所以这个applicative functor没有效果。 什么是用例,如果有任何给出Nothing

说,我和我有一个Maybe String ,我不知道它的价值。 我必须将这个Maybe赋予第三方函数,但希望它的结果首先经过一些Maybe (a -> b) 如果其中一些函数Nothing我会希望它们默默地返回它们的输入,而不是给出Nothing ,这就是数据丢失。

那么,在上面的例子中返回Nothing背后的想法是Nothing

那会怎么样? 这是类型签名:

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

所以这里的第二个参数是Maybe a类型,而结果需要是Maybe b类型。 你需要一些方法把a变成b ,你只有在第一个参数不是Nothing才能这样做。

这样的事情唯一可行的方法是,如果你有一个或多个类型为Maybe (a -> a)值,并且想要应用任何不是Nothing 但这对于(<*>)的一般定义来说太具体了。


编辑:因为它似乎是你真正关心的Maybe (a -> a)场景,所以这里有一些关于你可以用这种类型的值做些什么的例子:

保留所有功能并丢弃Nothing ,然后应用它们:

applyJust :: [Maybe (a -> a)] -> a -> a
applyJust = foldr (.) id . catMaybes

catMaybes函数为您提供仅包含Just值的列表,然后foldr它们组合在一起,从身份函数开始(如果没有要应用的函数,这将是您将获得的)。

或者,您可以采取功能,直到找到Nothing ,然后拯救:

applyWhileJust :: [Maybe (a -> a)] -> a -> a
applyWhileJust (Just f:fs) = f . applyWhileJust fs
applyWhileJust (Nothing:_) = id

这使用了与上面类似的想法,除了当它找到Nothing时它会忽略列表的其余部分。 如果你愿意,你也可以把它写成applyWhileJust = foldr (maybe (const id) (.)) id但这有点难以阅读......

<*>视为普通*运算符。 a * 0 == 0 ,对吗? 什么是无关紧要a 所以使用相同的逻辑, Just (const a) <*> Nothing == Nothing Applicative法律规定数据类型必须表现得像这样。

这有用的原因是, Maybe代表某种东西的存在 ,而不是缺少某种东西。 如果通过一系列函数传递Maybe值,如果一个函数失败,则表示发生了故障 ,并且该过程需要中止。

你提出的行为是不切实际的,因为它有很多问题:

  1. 如果失败的函数要返回其输入,则它必须具有类型a -> a ,因为返回的值和输入值必须具有相同的类型才能使它们可互换,具体取决于函数的结果
  2. 根据你的逻辑,如果你有Just (const 2) <*> Just 5 ,会发生什么? 在这种情况下,如何使行为符合Nothing案例?

另见Applicative法律

编辑:修复代码拼写错误,并再次

那么这个怎么样?

Just id <*> Just something

当您开始使用<*>来检测具有多个输入的函数时,会出现Nothing的用例。

(-) <$> readInt "foo" <*> readInt "3"

假设你有一个函数readInt :: String -> Maybe Int ,这将变成:

(-) <$> Nothing <*> Just 3

<$>只是fmap ,而fmap f Nothing is Nothing ,因此它fmap f Nothing为:

Nothing <*> Just 3

你现在能看到为什么这会产生什么? 表达式的原始含义是减去两个数字,但由于我们在第一次输入后未能生成部分应用的函数,我们需要传播该失败而不是仅仅构成一个与减法无关的好函数。

除了CA McCann的优秀答案之外,我想指出这可能是一个“免费定理”的案例,请参阅http://ttic.uchicago.edu/~dreyer/course/papers/wadler.pdf 本文的要点是,对于某些多态函数,给定类型签名只有一种可能的实现方式 ,例如fst :: (a,b) -> a除了返回该对的第一个元素之外别无选择 (或者是undefined),这可以证明。 这个属性可能看似违反直觉,但根植于函数对其多态参数的非常有限的信息(特别是它不能凭空创建一个)。

暂无
暂无

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

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