Joo*_*zan 5 monads haskell monad-transformers elm
我为榆树缺少单子而苦苦挣扎。实现Elm状态monad的库(http://package.elm-lang.org/packages/folkertdev/elm-state/latest/State)对我有很大帮助。
问题是,当我只想分别使用Result和State类型时,现在遇到了交替嵌套的Result和State类型的情况。
我尝试编写具有以下签名的函数,但似乎不可能,因为内部Result仅在评估外部State后才知道。
join : Result a (State s (Result a (State s x))) -> Result a (State s x)
Run Code Online (Sandbox Code Playgroud)
如果我将Result放入返回值中的State中,则可能会起作用,但是如果外部Result为,那会生成一个哑状态Err。
我认为正确的想法是做出既是结果又是状态的东西。熟悉Haskell monad变压器的人可以解释他们如何解决此类问题或提出替代解决方案吗?
这是一个出现问题的地方的粗略版本:
generateConstraints environment value
|> Result.map (State.map (\(value, valueC) ->
Result.map
(State.map2 (\this (body, bodyC) ->
( this
, valueC ++ bodyC ++ [(this, body)]
))
freshTypevar)
(generateConstraints (extend environment name value) body))
)
Run Code Online (Sandbox Code Playgroud)
我最终写了一个兼具两者的单子。我必须牺牲在状态被触及之前失败的能力,因为我需要能够在之后失败。
type alias Infer a = State Int (Result String a)
infer : a -> Infer a
infer x =
State.state (Ok x)
map : (a -> value) -> Infer a -> Infer value
map f x =
State.map (Result.map f) x
andThen : (a -> Infer b) -> Infer a -> Infer b
andThen f x =
State.andThen
(\r -> case r of
Ok v -> f v
Err e -> State.state <| Err e
)
x
andMap : Infer y -> Infer (y -> z) -> Infer z
andMap y =
andThen (\g -> map g y)
map2 : (a -> b -> c) -> Infer a -> Infer b -> Infer c
map2 f x y =
map f x
|> andMap y
map3 : (a -> b -> c -> d) -> Infer a -> Infer b -> Infer c -> Infer d
map3 f a b c =
map2 f a b
|> andMap c
map4 : (a -> b -> c -> d -> e) -> Infer a -> Infer b -> Infer c -> Infer d -> Infer e
map4 f a b c d =
map3 f a b c
|> andMap d
Run Code Online (Sandbox Code Playgroud)