Is there an inject equivalent for Haskell in the context of free monads

房东的猫 提交于 2019-12-05 14:08:10

This is covered in Data Types à la Carte. The Scala library you demonstrated looks like a fairly faithful translation of the original Haskell. The gist of it is, you write a class representing a relationship between a functor sup which "contains" a functor sub:

class (Functor sub, Functor sup) => sub :-<: sup where
    inj :: sub a -> sup a

(These days you might use a Prism, because they can both inject and project.) Then you can use the usual technique of composing the base functors of your free monads using the functor coproduct, implement :-<: for the two cases of Sum,

instance Functor f => f :-<: f where
    inj = id
instance (Functor f, Functor g) => f :-<: (Sum f g) where
    inj = InL
instance (Functor f, Functor g, Functor h, f :-<: g) => f :-<: (Sum h g) where
    inj = InR . inj

and make instruction sets composable by abstracting over the base functor.

ask :: Interact :-<: f => Free f String
ask = liftF $ inj $ Ask id

tell :: Interact :-<: f => String -> Free f ()
tell str = liftF $ inj $ Tell str ()

addCat :: DataOp :-<: f => String -> Free f ()
addCat cat = liftF $ inj $ AddCat cat ()

getCats :: DataOp :-<: f => Free f [String]
getCats = liftF $ inj $ GetCats id

Now you can write a program which uses both Interact and DataOp without making reference to a particular sum type.

myProgram :: (Interact :-< f, DataOp :-< f) => Free f ()
myProgram = ask >>= addCat

None of this is particularly better than the standard MTL approach, though.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!