Hackage documentation | Examples
joint
let you type expressions by effects that they produce. No free/freer monad, no GADTs and other fancy stuff - all you need is a functor composition. If you want to be able to use your on effect in this library you need to pick a joint schema
and write several instances (Functor
/Applicative
/Monad
). For better understanding it's recommend to read this explanation series: part 1, part 2, part 3.
Let’s imagine that we need to make an HTTP request, it’s IO
, that can throw HttpException
:
import qualified "wreq" Network.Wreq as HTTP
request :: (Monad t, Liftable IO t, Failable HttpException t) => t (Response ByteString)
request = lift (try @HttpException $ HTTP.get link) >>= lift
Wow, what is there? First, we lift
some IO
-action, then after >>=
we lift
Either
and we get an expression, that can be used in many effectful expressions than contain such two effects! We can delay using concrete transformers until we really need to evaluate them.
If you have some effectful expression, you can easy compose them:
let f = get :: Configured _ t => t _
let g = nothing :: Optional t => t _
let h = failure _ :: Failable _ t => t _
let x = f *> g *> h :: (Applicative t, Configured _ t, Optional t, Failable _ t) => t _
If you have concrete transformers, the order of effects doesn't matter, you can fit lifted effects to them:
let y = pure _ :: Reader _ :> State _ :> Either _ :> Maybe := Int
let z = pure _ :: State _ :> Either _ :> Maybe _ :> Reader := _
let x = f *> g *> h :: (Applicative t, Configured _ t, Optional t, Failable _ t) => t _
let xy = x *> y :: Reader _ :> State _ :> Either _ :> Maybe := _
let xz = x *> z :: State _ :> Either _ :> Maybe _ :> Reader := _
To interpret some effect you can use run
method:
let xy = x *> y :: Reader _ :> State _ :> Either _ :> Maybe := _
let xy' = run xy _ :: State _ :> Either _ :> Maybe := _
let xy'' = run xy' _ :: Either _ :> Maybe := _
let xy''' = run xy'' :: Maybe (Either _) _