说我有以下免费monad:
data ExampleF a = Foo Int a | Bar String (Int -> a) deriving Functor type Example = Free ExampleF -- this is the free monad want to discuss
我知道如何使用此monad。我可以写一些不错的助手:
foo :: Int -> Example () foo i = liftF $ Foo i () bar :: String -> Example Int bar s = liftF $ Bar s id
所以我可以用haskell编写程序,例如:
fooThenBar :: Example Int fooThenBar = do foo 10 bar "nice"
我知道如何打印,解释等。但是如何解析呢?
是否有可能编写一个解析器来解析任意程序,例如:
foo 12 bar nice foo 11 foo 42
所以我可以存储它们,序列化它们,在cli程序中使用它们,等等。
我一直遇到的问题是程序的类型取决于要解析的程序。如果一个程序结束foo
它的类型Example ()
,如果它有结束bar
它的类型Example Int
。
我不喜欢写解析器每一种可能的置换(这里很简单,因为只有两种可能,但是想象一下我们添加
Baz Int (String -> a)
,Doo (Int -> a)
,Moz Int a
,Foz String a
,... GET操作的繁琐,而且容易出错)。
也许我正在解决错误的问题?
要运行上述示例,您需要将其添加到文件的开头:
{-# LANGUAGE DeriveFunctor #-} import Control.Monad.Free import Text.ParserCombinators.Parsec
注意:我提出了包含此代码的要点。