我写了一个代表一些计算的monad。现在,我想定义计算应该是sequenced
的方式。所以,我将定义>>=
。但是,对流量的控制迫使我把注意力集中在a
的混淆类型上。我的意思是:
m >>= f =
a <- m
case a of
(ParticularParameterA) -> doSomething
..........
这是正确的解决方案吗?我的意思是:我没有函数式编程经验,所以我不确定是否可以。怎么做得更好?
答案 0 :(得分:2)
虽然case
语句和语法错误,但这个定义确实显然是荒谬的,因为来自do-block的绑定被转换为>>=
的使用。因此,您现有的代码已经定义了m >>= f = m >>= \a -> ...
,这是一个无限循环和空间泄漏。
答案 1 :(得分:1)
您的情况可能属于简单模式,即monad格式:
newtype MyMonad a = MyMonad { run :: State -> (a, State) }
其中State
是您自己设计的数据类型。关键是你可能有一个功能:
run :: MyMonad a -> State -> (a, State)
您可能需要在实现(&gt;&gt; =)时使用此功能:
m >>= f = MyMonad(\state -> let (x, newState) = run m state in
case x of
(ParticularParameterA) -> doSomething
..........
现在如果f::a -> MyMonad b
您的\state -> ...
函数必须返回(b, State)
,那么您可能希望在代码中的某处使用run (f x) newState
。
如果你的monadic类型是以下形式:
newtype MyMonad a = MyMonad { run :: State -> Maybe (a, State) }
newtype MyMonad a = MyMonad { run :: State -> Either String (a, State) }
然后你仍然使用run
函数,例如
m >>= f = MyMonad (\state -> case run m state of
Just (x, newState) -> run (f x) newState
Nothing -> Nothing)