>)Monad的实例和混淆(

在不同的问题中,我发现了有关使用Monads (->)实例的注释,例如实现无点风格。

至于我,这太抽象了。 好的,我在(->)上看到了Arrow实例,在我看来, (->)可以用于实例符号中,但不能用于类型声明中(这仅仅是另一个问题的东西)。

有没有人使用(->)作为Monad的实例? 或者一个好的链接?

很抱歉,如果这个问题可能已经在这里讨论过了,但是搜索“ (->) Monad实例”会给你很多点击,就像你想象的那样...因为几乎每个关于Haskell的问题都涉及(->)或者“Monad” 。


对于给定的类型r ,类型r -> a的函数可以被认为a使用环境类型r传递a的计算。 给定两个函数r -> aa -> (r -> b) ,很容易想象当给定一个环境时(也可以是r类型),可以构造这些r

可是等等! 这正是monads的意义所在!

所以我们可以为(->) r创建一个Monad实例,通过将r传递给fg来实现f >>= g g 。 这是(->) r的Monad实例。

要实际访问环境,可以使用id :: r -> r ,您现在可以将其视为在环境r运行并提供r 。 要创建本地子环境,您可以使用以下内容:

inLocalEnvironment :: (r -> r) -> (r -> a) -> (r -> a)
inLocalEnvironment xform f = env -> f (xform env)

这种将环境传递给计算的模式可以在本地进行查询并对其进行修改,这对于不仅仅是(->) r monad很有用,这就是为什么它被抽象为MonadReader类的原因,它使用比我更明智的名称这里用过:

http://hackage.haskell.org/packages/archive/mtl/2.0.1.0/doc/html/Control-Monad-Reader-Class.html

基本上,它有两种情况: (->) r ,我们在这里看到,和ReaderT rm ,这仅仅是一个newtype围绕包装r -> ma ,所以它是同样的事情(->) r单子我这里已经描述过,除了它提供了一些其他变换单子的计算。


要为(->) r定义一个monad,我们需要两个操作, return(>>=) ,并遵循三个定律:

instance Monad ((->) r) where

如果我们看看(->) r的回报签名

    return :: a -> r -> a

我们可以看到它只是常数函数,忽略了它的第二个参数。

    return a r = a

或者,

    return = const

要构建(>>=) ,如果我们用monad (->) r专门化它的类型签名,

    (>>=) :: (r -> a) -> (a -> r -> b) -> r -> b

实际上只有一个可能的定义。

    (>>=) x y z = y (x z) z

使用这个monad就像是给每个函数传递一个额外的参数r 。 您可以将其用于配置,或将选项传递到程序的深处。

通过验证三个monad定律,我们可以检查它是否是monad:

1. return a >>= f = f a 

return a >>= f 
= (b -> a) >>= f -- by definition of return
= (x y z -> y (x z) z) (b -> a) f -- by definition of (>>=)
= (y z -> y ((b -> a) z) z) f -- beta reduction
= (z -> f ((b -> a) z) z) -- beta reduction
= (z -> f a z) -- beta reduction
= f a -- eta reduction

2. m >>= return = m

m >>= return
= (x y z -> y (x z) z) m return -- definition of (>>=)
= (y z -> y (m z) z) return -- beta reduction
= (z -> return (m z) z) -- beta reduction
= (z -> const (m z) z) -- definition of return
= (z -> m z) -- definition of const
= m -- eta reduction

最终的单子法:

3. (m >>= f) >>= g  ≡  m >>= (x -> f x >>= g)

遵循类似的,容易的等式推理。

我们也可以为(( - >)r)定义一些其他的类,例如Functor,

instance Functor ((->) r) where

如果我们看一下签名

   -- fmap :: (a -> b) -> (r -> a) -> r -> b

我们可以看到它的正义构图!

   fmap = (.)

同样,我们可以创建一个Applicative的实例

instance Applicative ((->) r) where
   -- pure :: a -> r -> a
   pure = const

   -- (<*>) :: (r -> a -> b) -> (r -> a) -> r -> b
   (<*>) g f r = g r (f r)

有这些实例的好处是,它们允许您在操作函数时使用所有Monad和Applicative组合器。

有很多涉及到类实例( - >),例如,你可以手工编写含半幺群的实例(B - > A),在给定的一个Monoid a为:

enter code here
instance Monoid a => Monoid (b -> a) where
    -- mempty :: Monoid a => b -> a
    mempty _ = mempty
    -- mappend :: Monoid a => (b -> a) -> (b -> a) -> b -> a
    mappend f g b = f b `mappend` g b

但是鉴于Monad / Applicative实例,您还可以使用定义此实例

instance Monoid a => Monoid (r -> a) where
    mempty = pure mempty
    mappend = liftA2 mappend

使用(->) r或with的Applicative实例

instance Monoid a => Monoid (r -> a) where
    mempty = return mempty
    mappend = liftM2 mappend

(->) r使用Monad实例。

这里节省的资源很少,但是,例如,用于生成无点代码的@pl工具(由#haskell IRC通道上的lambdabot提供)会滥用这些实例。

链接地址: http://www.djcxy.com/p/47691.html

上一篇: >) instances of Monad and confusion about (

下一篇: Monads as adjunctions