【问题标题】:How do I access both the value and accumulator of a Writer monad within a 'do' block (PureScript)?如何在“do”块(PureScript)中访问 Writer monad 的值和累加器?
【发布时间】:2016-09-16 01:49:43
【问题描述】:

我现在正在学习 Writer monad,我不确定在 do 块中读取 monad 的值和累加器是否正确。例如,在下面的 coltzSeq 函数中,我想读取 Array 累加器的长度作为函数的最终计算。是否可以这样做或这是对 Writer 的不正确使用?显然,我可以让调用者读取最终数组的长度,或者我可以使用 State monad,但这只是我的练习。

module Main where

import Prelude
import Data.Tuple
import Control.Monad.Writer
import Math (remainder, (%))
import Data.Int (toNumber, fromNumber)
import Control.Monad.Eff.Console (logShow)

coltz :: Number -> Number
coltz n = case (n % 2.0 == 0.0) of
            true  -> n / 2.0
            false -> 3.0 * n + 1.0

coltzW :: Number -> Writer (Array Number) Number
coltzW n = do
  tell [n]
  pure $ coltz n

-- Computes a coltz sequence and counts how many
-- steps it took to compute
coltzSeq :: Number -> Writer (Array Number) Int
coltzSeq n = do

  -- Can read the value in the writer
  -- but not the writer's internal state
  v <- (coltzW n)
  let l = 1

  -- Can read the value and the internal
  -- state, but it's not bound to the monad's context.
  -- let a = runWriter (coltzW n)
  -- let v = fst a
  -- let l = length (snd a)
  case (v) of
    1.0 -> pure $ l
    _ -> to1 v

编辑: 我尝试了 gb. 的建议并尝试使用类型为 (Monoid w, Monad m) =&gt; forall w m a b. MonadWriter w m =&gt; (w -&gt; b) -&gt; m a -&gt; m (Tuple a b)listens 函数。如果我们在这种情况下使用id,类型将是...

MonadWriter w m => (w -> b) -> m a -> m (Tuple a b)

w = Array Number
m = WriterT (Array Number) Identity (alias: Writer (Array Number) )
b = Array Number
a = Number

(Array Number -> Array Number) ->
Writer (Array Number) Number ->
Writer (Array Number) (Tuple Number (Array Number))

所以listens id 接受Writer (Array Number) Number),并返回一个值为当前 Writer 状态的 Writer(因为我们使用了id)。但是,我尝试和使用listens的所有方式都不断出现类型错误@

to1 :: Number -> (Writer (Array Number)) Int
to1 n = do
  v <- (coltzW n)
  -- a <- snd <$> listens id
  -- let l = snd <$> (listens id (execWriter (coltzW n)))
  -- let l = execWriter (listens id (coltzW n))

  -- Seems like this one should work to get Array Number
  -- let l = snd <$> (listens id (coltzW n))

  case (v) of
    1.0 -> pure 1
    _   -> to1 v

编辑2: 我想出了我需要做什么。由于某种原因,我需要在使用listens 时添加类型注释。

lengthOfSeq :: Writer (Array Number) Int -> Writer (Array Number) Int
lengthOfSeq c = do
  -- Without type annotation, I get this error...
  -- No type class instance was found for
  --                                                                             
  -- Control.Monad.Writer.Class.MonadWriter (Array t0)                       
  --                                        (WriterT (Array Number) Identity)
  --                                                                             
  -- The instance head contains unknown type variables. Consider adding a type annotation.
  Tuple a w <- (listens id c :: Writer (Array Number) (Tuple Int (Array Number)))
  pure $ length w

to1 :: Number -> (Writer (Array Number)) Int
to1 n = lengthOfSeq $ seq n
  where
  seq n = do
    v <- coltzW n
    case (v) of
      1.0 -> do
        pure 1
      _   -> seq v

【问题讨论】:

    标签: monads purescript writer-monad


    【解决方案1】:

    我认为 listens 是您正在寻找的功能:https://pursuit.purescript.org/packages/purescript-transformers/1.0.0/docs/Control.Monad.Writer#v:listens,如果我理解正确的话,您正在尝试做什么。

    如果您对转换值不感兴趣,可以传递id,如果您只想获取累积值,那么a &lt;- snd &lt;$&gt; listens id 应该可以解决问题。

    【讨论】:

    • 我想我在 listens 的机制上遗漏了一些东西。我添加了关于监听类型签名的编辑。你觉得我的想法对吗?我一直在尝试使用监听的变体,但我似乎无法让它发挥作用。
    • 感谢您的帮助,我想我想通了 - 出于某种原因,我不得不在使用监听时添加类型注释,例如 a &lt;- snd &lt;$&gt; (listens id c :: Writer (Array Number) (Tuple Int (Array Number))) 否则我会收到错误“找不到类型类实例for Control.Monad.Writer.Class.MonadWriter (Array t0) (WriterT (Array Number) Identity)"
    • 很高兴你知道了!由于我们目前没有函数依赖关系,因此对其中一些转换器函数的推断存在问题,但它们将在下一个版本 (0.10) 中推出。
    【解决方案2】:

    您无法访问当前累加器。 Writer 是只写的。如果您需要电流累加器,请使用 State 而不是 Writerlisten 只能给你一个完成计算的累加器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-01-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多