我有许多方法在其定义中都有样板代码,请看上面的例子。
baseRequest.delete({method: "deleteUser.req", id: id}, {}, function (response) {
如您所见,replace:: Term -> Term -> Formula -> Formula
replace x y (Not f) = Not $ replace x y f
replace x y (And f g) = And (replace x y f) (replace x y g)
replace x y (Or f g) = Or (replace x y f) (replace x y g)
replace x y (Biimp f g) = Biimp (replace x y f) (replace x y g)
replace x y (Imp f g) = Imp (replace x y f) (replace x y g)
replace x y (Forall z f) = Forall z (replace x y f)
replace x y (Exists z f) = Exists z (replace x y f)
replace x y (Pred idx ts) = Pred idx (replace_ x y ts)
函数的定义遵循一种模式。我希望函数具有相同的行为,简化他的定义,可能使用一些模式匹配,可能在参数上使用通配符replace
或_
,如:
X
为避免以下定义:
replace x y (X f g) = X (replace x y f) (replace x y g)
有什么办法吗?忘记函数的目的,它可以是任何东西。
答案 0 :(得分:6)
如果你有许多应该以统一的方式对待的构造函数,你应该让你的数据类型反映出来。
data BinOp = BinAnd | BinOr | BinBiimp | BinImp
data Quantifier = QForall | QExists
data Formula = Not Formula
| Binary BinOp Formula Formula -- key change here
| Quantified Quantifier Formula
| Pred Index [Formula]
现在所有二元运算符的模式匹配都更容易:
replace x y (Binary op f g) = Binary op (replace x y f) (replace x y g)
要保留现有代码,您可以启用PatternSynonyms
并定义And
,Or
的旧版本,等等:
pattern And x y = Binary BinAnd x y
pattern Forall f = Quantified QForall f
答案 1 :(得分:3)
我不完全确定这是你在找什么,但你可以做到以下几点。我们的想法是,您可以考虑将公式抽象为另一种类型(在您的情况下通常为Term
)。然后,您可以定义映射公式的含义。我试图复制你的数据定义,虽然我对Formula
有一些问题 - 即所有构造函数似乎都需要另一个Formula
......
{-# LANGUAGE DeriveFunctor #-}
data Formula a
= Not (Formula a)
| And (Formula a) (Formula a)
| Or (Formula a) (Formula a)
| Biimp (Formula a) (Formula a)
| Imp (Formula a) (Formula a)
| Forall a (Formula a)
| Exists a (Formula a)
| Pred a (Formula a)
deriving (Functor)
data Term = Term String {- However you define it, doesn't matter -} deriving (Eq)
replace :: (Functor f, Eq a) => a -> a -> f a -> f a
replace x y = fmap (\z -> if x == z then y else z)
有趣的是,现在replace
函数可以应用于任何仿函数 - 它甚至可以用作列表的replace
!
replace 3 9 [1..6] = [1,2,9,4,5,6]
编辑作为事后的想法,如果你要实现替换样式替换公式中的术语可以被遮蔽(通常的作用域规则),你可能最终会做这样的事情:
replace' :: (Eq a) => a -> a -> Formula a -> Formula a
replace' x y f@(Forall z _) | x == z = f
replace' x y f@(Exists z _) | x == z = f
replace' x y f@(Pred z _) | x == z = f
replace' x y formula = fmap (replace' x y) formula
这不是那么可爱,但也不是一个问题直截了当。
答案 2 :(得分:1)
Data.Functor.Foldable抽象出递归数据结构的模式:
import Data.Functor.Foldable
data FormulaF t
= Not t
| And t t
| Or t t
| Biimp t t
| Imp t t
| Forall A t
| Exists A t
| Pred B C
deriving (Functor, Foldable, Traversable)
type Formula = Fix FormulaF
replace :: Term -> Term -> Formula -> Formula
replace x y = cata $ \case ->
Pred idx ts -> Pred idx (replace_ x y ts)
f -> f
顺便提一下,请注意replace x y (Forall x (f x)) = Forall x (f y)
:Substitution is the process of replacing all free occurences of a variable in an expression with an expression.