我有一个简单的 Expr
AST,我可以轻松地将它转换为 String
。
import Prelude hiding (Foldable)
import qualified Prelude
import Data.Foldable as F
import Data.Functor.Foldable
import Data.Monoid
import Control.Comonad.Cofree
data ExprF r = Const Int
| Add r r
deriving ( Show, Eq, Ord, Functor, Prelude.Foldable )
type Expr = Fix ExprF
testExpr = Fix $ Add (Fix (Const 1)) (Fix (Const 2))
convertToString :: Expr -> String
convertToString = cata $ \case
e@(Const x) -> show x
e@(Add x y) -> unwords [x, "+", y]
现在我想要添加一个额外的数据。
所以我尝试使用Cofree
type LineNumber = Int
type Expr2 = Cofree ExprF LineNumber
我可以将
Expr
转换为Expr2
。addLineNumbers :: Expr -> Expr2
addLineNumbers = cata $ \case
e@(Const _) -> 1 :< e
e -> 2 :< e
但我不知道如何将Expr2
转换为String
convertToString2 :: Expr2 -> String
convertToString2 = cata $ \case
e@(_ :< (Const x)) -> show x
e@(_ :< (Add x y)) -> unwords [x, "+", y]
此外,Cofree是否是解决此注释问题的最佳方式?
Free
是归纳的,而Cofree
是余归纳的。也就是说,使用任意函子的(全)代数来“拆解”(行为良好的)自由单子态是保证终止的,并且使用余代数来“建立”余自由协单态是保证生产力的。反过来则不成立。 - Benjamin Hodgson