是否有任何直觉可以理解在Monad中加入两个函数?

Kam*_*mel 12 monads haskell functional-programming category-theory

join定义bind以将组合数据结构展平为单个结构.

从类型的系统视图,(+) 7 :: Num a => a -> a可被视为一个Functor,(+) :: Num a => a -> a -> a可以被认为是一个FunctorFunctor,如何获得一些关于它的直觉,而不是仅仅依靠类型系统?为什么join (+) 7 === 14

即使可以通过函数绑定过程手动步进来获得最终结果,但如果给出一些直觉,那将是很好的.

这是来自NICTA演习.

-- | Binds a function on the reader ((->) t).
--
-- >>> ((*) =<< (+10)) 7
-- 119
instance Bind ((->) t) where
  (=<<) ::
    (a -> ((->) t b))
    -> ((->) t a)
    -> ((->) t b)
  (f =<< a) t =
    f (a t) t

-- | Flattens a combined structure to a single structure.
--
-- >>> join (+) 7
-- 14
join ::
  Bind f =>
  f (f a)
  -> f a
join f =
  id =<< f

*Course.State> :t join (+)
join (+) :: Num a => a -> a
*Course.State> :t join
join :: Bind f => f (f a) -> f a
*Course.State> :t (+)
(+) :: Num a => a -> a -> a
Run Code Online (Sandbox Code Playgroud)

dup*_*ode 10

如何获得一些直觉而不仅仅依靠类型系统?

我宁愿说依赖类型系统是构建特定直觉的好方法.类型join是:

join :: Monad m => m (m a) -> m a
Run Code Online (Sandbox Code Playgroud)

专门(->) r,它变成:

(r -> (r -> a)) -> (r -> a)
Run Code Online (Sandbox Code Playgroud)

现在让我们尝试定义join函数:

-- join :: (r -> (r -> a)) -> (r -> a)
join f = -- etc.
Run Code Online (Sandbox Code Playgroud)

我们知道结果必须是一个r -> a函数:

join f = \x -> -- etc.
Run Code Online (Sandbox Code Playgroud)

但是,我们不知道在所有关于什么什么ra类型,因此,我们知道没有什么讲究f :: r -> (r -> a)x :: r.我们的无知意味着我们可以用它们做一件事:x作为一个论点,传递给ff x:

join f = \x -> f x x
Run Code Online (Sandbox Code Playgroud)

因此,join函数传递相同的参数两次,因为这是唯一可能的实现.当然,这种实施只是一种适当的monadic,join因为它符合monad法则:

join . fmap join = join . join
join . fmap return = id
join . return = id
Run Code Online (Sandbox Code Playgroud)

验证这可能是另一个很好的练习.


Sil*_*olo 7

与monad的传统类比一起作为计算的上下文,join是一种组合上下文的方法.让我们从你的例子开始吧.join (+) 7.使用函数作为monad意味着读者monad.(+ 1)是一个读者monad,它采用环境并添加一个环境.因此,(+)将是读者monad中的读者monad.外部读者monad占用环境 n并返回表单的读者(n +),这将带来一个新的环境.join简单地组合两个环境,以便您提供一次,并将给定的参数应用两次.join (+) === \x -> (+) x x.

现在,更一般地说,让我们看看其他一些例子.该Maybe单子代表潜在的故障.值Nothing是计算失败,而a Just x是成功.a Maybe中的a Maybe是可能失败两次的计算.价值Just (Just x)显然是成功的,所以加入产生Just x.A Nothing或a Just Nothing表示某些时候出现故障,因此加入可能的故障应该表明计算失败,即Nothing.

可以对列表monad进行类似的类比,其join仅仅concat是作者monad,其使用monoidal运算符<>来组合所讨论的输出值或任何其他monad.

join是monad的一个基本属性,它的操作使得它比functor或applicative functor强大得多.可以映射函数,应用程序可以是序列,monad可以组合.分类地,monad通常被定义为joinreturn.碰巧的是,在Haskell中,我们发现它更方便的来定义它return,(>>=)fmap,但两人的定义已被证明的代名词.

  • 这个答案可能更准确的一点是像"[使用]一个函数作为monad"这样的段落,"`(+)`将是读者monad中的读者monad".诸如`(+)`之类的值不是monad; 它们是一元价值观.它是类型构造函数,例如`( - >)r`是monad.另请参阅leftaroundabout对上述问题的评论. (2认同)