How to combine the result and the state of knitting?

I struggle with the lack of scammers. The library implementing the state monad for Elm ( http://package.elm-lang.org/packages/folkertdev/elm-state/latest/State ) helped me a bit.

The problem is that I was faced with a situation where I have successively nested Result and State types, when I want only one of them.

I tried to write a function with the following signature, but this seems impossible, because the internal result is known only after evaluating the external state.

join : Result a (State s (Result a (State s x))) -> Result a (State s x)

Maybe this will work if I put the result in a state in the return value, but this will create a dummy state in case there is an external result Err.

I think the right idea would be to do something that is the result and the state. Can someone familiar with the transformers of the Haskell monks explain how they solve this problem or offer an alternative solution?

Here is a rough version of one place where the problem occurs:

  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))
  )
+4
source share
2 answers

In the end, I wrote a monad, which is. I had to sacrifice the opportunity to fail before it touched the state, because I needed to fail after.

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
+2
source

Can someone familiar with Haskell monad transformers explain how they solve this problem or offer an alternative solution?

, . Haskell:

type EffM a s x = Either a (State s x)

, . 2 :

type TransM a s x = EitherT a (State s) x

, T , x parens. .

, State , , Either "" " ", "" , . , , - , .

, , join , Monad.

import Control.Monad.State
import Control.Monad.Trans.Either
import Control.Monad

type Eff e s a = EitherT e (State s) a

-- type the following in REPL

λ :t join
join :: Monad m => m (m a) -> m a

λ :t join :: Eff e s (Eff e s a) -> Eff e s a
join :: Eff e s (Eff e s a) -> Eff e s a
     :: Eff e s (Eff e s a) -> Eff e s a

-- the slightly cryptic output above means that it typechecks correctly

, Haskell 1. , , EitherState ( StateEither - ), , join . , EitherT Elm.


1 . , /Free, , , . , .

2 Monad, , , x Monad ( Either , , ).

+3

Source: https://habr.com/ru/post/1673391/


All Articles