【问题标题】:How to define instances of Applicative and Monad when working with a constructor defined using record syntax在使用使用记录语法定义的构造函数时如何定义 Applicative 和 Monad 的实例
【发布时间】:2020-11-28 09:22:12
【问题描述】:

我正在尝试为 RWS 的 Applicative 和 Monad 定义实例,但一定有一些我遗漏的东西。对于pure,我收到一个发生检查错误。尽管 f 的类型为 a,但它一定与我将 RWS f 作为 pure 的结果给出的事实有关。我不明白如何访问RWS(r、w 和 s)的其他参数。如果有人详细解释一些概念,例如newtype 定义,我将不胜感激。据我了解,我们定义了一个新类型RWS,它有 4 个参数(r、w、s 和 a)。这种类型是使用构造函数 (fromRWS) 定义的,它对参数执行一些操作。如果我错了,请纠正我。如果这是正确的,RWS 是由 4 个参数定义的还是由 fromRWS 定义的?

进一步,<*> 的实现会产生类型错误。它说 fromRWS2 应用于太少的参数。不过,我没有看到这个问题,因为我使用了相同的 where 子句方法来解决变量环境的类似问题。我可以使用哪些替代品?

定义Monad时,我只得到了parse error on input RWS

请帮我定义实例。

这是我的代码:

module RWS where

newtype RWS r w s a = RWS { fromRWS :: r -> s -> (a, s, w) }

instance Functor (RWS r w s) where
  fmap f (RWS rws) = RWS $ \r s -> let (a,s',w) = rws r s in (f a, s', w)

instance Monoid w => Applicative (RWS r w s) where
    -- pure a -> RWS r w s a
    pure f = RWS f
    -- (<*>) :: RWS r w s (a -> b) -> RWS r w s a -> RWS r w s b 
    RWS f <*> RWS a = RWS fromRWS2
                            where fromRWS2 r1 s1 = f a

instance Monoid w => Monad (RWS r w s) where
   --return :: a -> RWS r w s a
   return x = RWS x
   --(>>=)  :: (RWS r w s a) -> (a -> (RWS r w s b)) -> (RWS r w s b)
  RWS fr >>= f = f fr

【问题讨论】:

    标签: haskell monads record applicative


    【解决方案1】:

    如果我们把RWS写成这样可能会更清楚

    newtype RWS r w s a = MakeRWS { fromRWS :: (r -> s -> (a, s, w)) }
    

    这个定义给你带来了三件事:

    • 一个 type 构造函数 RWS 采用四个 r w s a 参数。
    • data 构造函数 MakeRWS 类型为 (r -&gt; s -&gt; (a, s, w)) -&gt; RWS r w s a
    • fromRWS 类型的字段访问器 RWS r w s a -&gt; (r -&gt; s -&gt; (a, s, w))

    正如我们所见,数据构造函数MakeRWS 应该应用于一个函数来构造RWS r w s a 类型的值。

    在您的pure 实现中,您将MakeRWS 应用于a 类型的值而不是函数。这就是你纯实现的问题所在。

    正如您在评论中指出的,pure 的类型应该是

    a -> RWS r w s a
    

    但如果它有效,您的实现将具有这种类型:

    (r -> s -> (a, s, w)) -> RWS r w s a
    

    正确的实现是

    pure a = MakeRWS (\_r s -> (a, s, mempty)
    

    您的 monad 实现无法解析,因为您在 return 行上的缩进与以 RWS 开头的行不同。

    【讨论】:

    • 我设法修复了pure。缩进更改后,&lt;*&gt; 和 Monad 仍然存在问题。更改后在哪里可以更新代码?这在原始帖子中是否允许?
    • @andy_bruja 编辑不能使答案无效,所以可能不要编辑它。 :)
    【解决方案2】:

    只需按照类型。对于任何给定的事情,我们只能做这么多:

    -- newtype RWS r w s a  =  RWS { fromRWS :: r -> s -> (a, s, w) }
    
    -- .....
    
        RWS tf <*> RWS ta  =  RWS tfa
            where 
            tfa r1 s1  =  (f a, s?, w2 ?? w3)  -- what is ?
               where                           -- what is ??
               (f, s2, w2) = tf r1 s1 
               (a, s3, w3) = ta r1 s2 
    

    对于单子也是如此。首先return = pure 和另一个答案向您展示了如何定义它:

        pure a  =  RWS ta
            where
            ta _r s  =  (a, s, mempty)
    

    那么绑定就是

       --(>>=)  :: (RWS r w s a) -> (a -> (RWS r w s b)) -> (RWS r w s b)
      (RWS f) >>= k  =  RWS g
           where
           -- RWS f :: RWS r w s a
           --     f :: r -> s -> (a, s, w)
           -- RWS g :: RWS r w s b
           --     g :: r -> s -> (b, s, w)
           g r1 s1  =  ???                     -- what is ???
                where
                (a, s2, w2) = f r1 s1
                (RWS h)     = k a
                -- RWS h :: RWS r w s b
                --     h :: r -> s -> (b, s, w)
                (b, s3, w3) = h r1 s????       -- what is ????
    

    【讨论】:

      猜你喜欢
      • 2019-06-30
      • 1970-01-01
      • 1970-01-01
      • 2022-11-04
      • 2021-04-28
      • 2023-03-11
      • 1970-01-01
      • 2021-03-09
      相关资源
      最近更新 更多