我现在正在了解Writer monad,而且我不确定是否想要在{{1}内读取monad的值和累加器是否正确阻止。例如,在下面的coltzSeq函数中,我想读取Array累加器的长度作为函数的最终计算。是否可以这样做或者这是对Writer的错误使用?显然,我可以让调用者读取最终数组的长度,或者我可以使用State monad,但这对我来说只是一个练习。
do
编辑:
我尝试了gb。的建议,并尝试使用类型为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
的{{1}}函数。如果我们在此上下文中使用listens
,则类型为...
(Monoid w, Monad m) => forall w m a b. MonadWriter w m => (w -> b) -> m a -> m (Tuple a b)
因此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))
,并返回一个值为当前Writer状态的Writer(因为我们使用了listens id
)。但是,我一直在尝试使用Writer (Array Number) Number)
id
EDIT2:
我想出了我需要做什么。出于某种原因,我需要在使用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
答案 0 :(得分:1)
我认为listens
是您正在寻找的功能:https://pursuit.purescript.org/packages/purescript-transformers/1.0.0/docs/Control.Monad.Writer#v:listens,如果我正确理解您正在尝试做什么。
如果您对转换价值不感兴趣,可以传递id
,如果您只想获得累计值,那么a <- snd <$> listens id
就可以了。
答案 1 :(得分:0)
您无法访问当前累加器。 Writer
是只写的。如果需要当前累加器,请使用State
代替Writer
。 listen
只能为您提供已完成计算的累加器。