我正在尝试扩展此博客文章中解释的玩具示例。
{-# LANGUAGE DeriveFunctor #-}
{-# LANGUAGE FlexibleContexts #-}
module FreeToy where
import Control.Monad.State
import Control.Monad.Free
import Data.Map (Map)
import qualified Data.Map as M
-- defining commands
data Toy a next =
Output a next
| AnnoyingOutput a (String -> next)
| Done
deriving (Functor)
-- lifing commands to free monad level
output :: a -> Free (Toy a) ()
output x = liftF $ Output x ()
annoyingOutput :: a -> Free (Toy a) {-some type-}
annoyingOutput x = liftF $ AnnoyingOutput x {-some function-}
done :: Free (Toy a) r
done = liftF $ Done
-- defining one of the interpreter
runToy :: (Show a, Show r) => Free (Toy a) r -> String
runToy (Free (Output a x)) =
"output " ++ show a ++ "\n" ++ runToy x
runToy (Free (AnnoyingOutput a f)) =
"annoying output " ++ show a ++ runToy (f "blah blah blah \n")
runToy (Free Done) =
"done\n"
runToy (Pure r) =
"return " ++ show r ++ "\n"
我尝试添加的新内容是AnnoyingOutput a (String -> next)
这将需要一些东西并返回字符串消息。我是结构,同时使用liftF
函数将它提升到 Free monad 级别。请帮我填空,适当的解释是可观的。
编辑:添加示例
module Main where
import FreeToy
import Control.Monad.Free
program :: Free (Toy String) ()
program = do
output "something"
x <- annoyingOutput "something else"
output x
done
main :: IO ()
main = putStrLn $ runToy program