I am trying to translate this Scala catsexample about creating free monads.
The essence of the example is the decomposition of individual problems into separate data types:
data Interact a = Ask (String -> a) | Tell String a deriving (Functor)
data DataOp = AddCat String | GetAllCats [String] deriving (Functor)
type CatsApp = Sum Interact DataOp
Without these two separate issues, I would construct a βlanguageβ for operations Interactas follows:
ask :: Free Interact String
ask = liftF $ Ask id
tell :: String -> Free Interact ()
tell str = liftF $ Tell str ()
However, if I want to use askit tellin a program that also uses it DataOp, I cannot define them with the types indicated above, since such a program will have a type:
program :: Free CatsApp a
In catsto determine the operations telland askthey use the class InjectKand method injectfrom Free:
class Interacts[F[_]](implicit I: InjectK[Interact, F]) {
def tell(msg: String): Free[F, Unit] = Free.inject[Interact, F](Tell(msg))
def ask(prompt: String): Free[F, String] = Free.inject[Interact, F](Ask(prompt))
}
, , (DataOp , Interact ) ( ).
, Haskell?