Modulepolysemy-zoo-0.8.2.0Haskell2010
Polysemy.Operators
Operators meant as replacements for traditional Sem type and Member / Members constraints, that allow you to specify types of your actions and interpreters in more concise way, without mentioning unnecessary details:
foo :: Member (Embed IO) r => String -> Int -> Sem r ()
can be written simply as:
foo :: String -> Int -> IO ~@> ()
Working example with operators:
import Data.Function
import Polysemy
import Polysemy.Operators
import Polysemy.Random
data ConsoleIO m a where
WriteStrLn :: String -> ConsoleIO m ()
ReadStrLn :: ConsoleIO m String
ShowStrLn :: Show a => a -> ConsoleIO m ()
makeSem ''ConsoleIO
-- runConsoleIO :: Member (Embed IO) r => Sem (ConsoleIO : r) a -> Sem r a
runConsoleIO :: ConsoleIO : r @> a -> IO ~@ r @> a
runConsoleIO = interpret \case
WriteStrLn s -> sendM $ putStrLn s
ReadStrLn -> sendM getLine
ShowStrLn v -> sendM $ print v
main :: IO ()
main = program
& runConsoleIO
& runRandomIO
& runM
-- program :: Members '[Random, ConsoleIO] r => Sem r ()
program :: '[Polysemy.Random, ConsoleIO] >@> ()
program = do
writeStrLn "It works! Write something:"
val <- readStrLn
writeStrLn $ "Here it is!: " ++ val
num <- random @Int
writeStrLn $ "Some random number:"
showStrLn num
Please keep in mind that constraints created through these operators are limited to the action they are being used on, for example:
foo :: (forall x. r @> x -> IO x)
-> IO (forall a. Foo : r @> a -> IO ~@ r @> a)
The first argument in the signature above won't have access to the
(IO ~@) constraint in the result - in such cases, use a normal
constraint instead:
foo :: Member (Embed IO) r
=> (forall x. r @> x -> IO x)
-> IO (forall a. Foo : r @> a -> r @> a)
See the documentation of specific operators for more details.
- 9 types
- Packagepolysemy-zoo-0.8.2.0
- Exports9
- LanguageHaskell2010
- LicenceBSD-3-Clause
- SourceOperators.hs
Sem operators
3 declarationsInfix equivalents of Sem with versions for specifiying list of effects (@>), single effect (@-) and single monad (@~) as effects of union. Use (>@>), (-@>) or (~@>) instead if you are not making any transformations on union and just want to use some members instead.
Examples:
Sem with list of multiple effects:
foo :: Sem (State Int : r) ()
can be written as:
foo :: State Int : r @> ()
Sem with list of one effect:
foo :: Sem '[State Int] ()
can be written as both (with the latter preferred):
foo :: '[State Int] @> ()
and:
foo :: State Int @- ()
where effect without list gets put into one automatically.
Sem with exactly one, lifted monad:
foo :: Sem '[Embed IO] ()
can be written simply as:
foo :: IO @~ ()
and will be automatically lifted and put into list.
Member operators
3 declarationsInfix equivalents of Member(s) constraint used directly in return type, specifiying list of members (>@), single member (-@) or single monad (~@), meant to be paired with some of the Sem operators ((@>), (@-) and (@~)). Use (>@>), (-@>) or (~@>) instead if you are not making any transformations on union and just want to use some members instead.
Examples:
List of multiple members:
foo :: Members '[State Int, Input String] r => Sem (Output [String] : r) () -> Sem r ()
can be written as:
foo :: Output [String] : r @> () -> '[State Int, Input String] >@ r @> ()
One member:
foo :: Member (State Int) r => Sem (Output [String] : r) () -> Sem r ()
can be written as both (with the latter preferred):
foo :: Output [String] : r @> () -> '[State Int] >@ r @> ()
and:
foo :: Output [String] : r @> () -> State Int -@ r @> ()
Exactly one, lifted monad as a member:
foo :: Member (Embed IO) r => Sem (Output [String] : r) () -> Sem r ()
can be written simply as:
foo :: Output [String] : r @> () -> IO ~@ r @> ()
Combined operators
3 declarationsJoined versions of one of (>@), (-@), (~@) and (@>) with implicit, hidden list of effects in union --- suited for actions that only use one Sem in their type.
Examples:
List of members over some Sem:
foo :: Members '[State String, Input Int] r => String -> Int -> Sem r ()
can be written as:
foo :: String -> Int -> '[State String, Input Int] >@> ()
Single member:
foo :: Member (Input Int) r => String -> Int -> Sem r ()
can be written as both (with the latter preferred):
foo :: String -> Int -> '[Input Int] >@> ()
and:
foo :: String -> Int -> Input Int -@> ()
Exactly one, lifted monad as a member:
foo :: Member (Embed IO) r => Sem r ()
can be written simply as:
foo :: IO ~@> ()