我已经开始为大学课程学习Haskell,并且编写了具有模式匹配功能的函数(称为Simplify
)。但是我不确定如何优化我的代码,因为我觉得代码太难了。
无论如何,这是我编写的代码:
data Proposition = Proposition Bool
| Const Bool
| Var String
| And Proposition Proposition
| Or Proposition Proposition
| Not Proposition deriving (Show, Eq)
simplify :: Proposition -> Proposition
simplify (And _ (Const False)) = (Const False)
simplify (And (Const False) _) = (Const False)
simplify (And p (Const True)) = simplify p
simplify (And (Const True) p) = simplify p
simplify (Or _ (Const True)) = (Const True)
simplify (Or (Const True) _) = (Const True)
simplify (Or a b) = simplify (Or (simplify a) (simplify b))
simplify (Const b) = (Const b)
simplify (Var v) = (Var v)
simplify (Not (Const True)) = (Const False)
simplify (Not (Const False)) = (Const True)
simplify (Not p) = simplify (Not (simplify p))
答案 0 :(得分:2)
您似乎通常希望遵循该模式
对我来说,这建议使用recursion-schemes
软件包。
{-# language TemplateHaskell, TypeFamilies, DeriveTraversable #-}
import Data.Functor.Foldable
import Data.Functor.Foldable.TH
data Proposition
= Const Bool
| Var String
| And Proposition Proposition
| Or Proposition Proposition
| Not Proposition
deriving (Show, Eq)
makeBaseFunctor ''Proposition
这神奇地生成了一个类型
data PropositionF x
= ConstF Bool
| VarF String
| AndF x x
| OrF x x
| NotF x
deriving (Functor, Foldable, Traversable)
以及一些相关实例。请注意,PropositionF
用其类型参数的副本替换每次出现的Proposition
。现在您可以写
simplify :: Proposition -> Proposition
simplify = cata go
where
go :: PropositionF Proposition -> Proposition
go (AndF (Const True) x) = x
go (AndF f@(Const False) _) = f
go (AndF x (Const True)) = x
go (AndF _ f@(Const False)) = f
go (OrF t@(Const True) _) = t
go (OrF (Const False) x) = x
go (OrF _ t@(Const True)) = t
go (OrF x (Const False)) = x
go (NotF (Const x)) = Const (not x)
go x = embed x -- Catch-all: no rules apply
所有递归简化都是“自动”处理的,所有“这里没有令人兴奋的”情况都在一行中处理。