haskell-类型-函数-树

haskell-类型-函数-树,haskell,types,tree,Haskell,Types,Tree,对于haskell的练习,我想实现一个游戏,在这个游戏中,学生/学生应该好玩地学习一些代数 作为基本数据类型,我希望使用树: 具有存储了标签和代数运算符的节点 具有标签和变量(类型字符串)或数字的叶子 现在我想定义一下 data Tree = Leaf {l :: Label, val :: Expression} | Node {l :: Label, f :: Fun, lBranch :: Tree, rBranch :: Tree} data Fun = "on

对于haskell的练习,我想实现一个游戏,在这个游戏中,学生/学生应该好玩地学习一些代数

作为基本数据类型,我希望使用树:

  • 具有存储了标签和代数运算符的节点
  • 具有标签和变量(类型字符串)或数字的叶子
现在我想定义一下

data Tree = Leaf {l :: Label, val :: Expression}
          | Node {l :: Label, f :: Fun, lBranch :: Tree, rBranch :: Tree}

data Fun = "one of [(+),(*),(-),(/),(^)]"

-- type Fun = Int -> Int 
行得通

我想的下一件事是使树“等价”——因为乘法/加法是可交换的,人们可以简化乘法的加法等所有代数运算。 我还必须通过搜索树-我认为是最好的标签,这是一个好办法


有什么想法需要寻找什么标签/短语以及如何解决“数据乐趣”

看起来你想构建一个符号代数系统。关于这个问题有大量不同的文献


您不希望将运算符表示为
Int->Int
,因为这样您就无法检查任何给定函数实现的操作,然后为简化等操作实现窥视孔优化。因此,一个简单的枚举数据类型就可以做到这一点,然后编写函数
eval
,该函数实际计算您的树。

展开Edward Z.Yang的回答:

这里定义运算符的最简单方法可能是作为数据类型,以及叶节点中原子值的类型和整个表达式树:

data Fun = Add | Mul | Sub | Div | Exp deriving (Eq, Ord, Show)

data Val a = Lit a | Var String deriving (Eq, Ord, Show)

data ExprTree a = Node String Fun (ExprTree a) (ExprTree a)
                | Leaf String (Val a)
    deriving (Eq, Ord, Show)
然后,您可以将
exprtreea
定义为
Num
等的实例:

instance (Num a) => Num (ExprTree a) where
    (+) = Node "" Add
    (*) = Node "" Mul
    (-) = Node "" Sub
    negate = Node "" Sub 0
    fromInteger = Leaf "" . Lit
…允许以非常自然的方式创建未标记的表达式:

*Main> :t 2 + 2
2 + 2 :: (Num t) => t
*Main> 2 + 2 :: ExprTree Int
Node "" Add (Leaf "" (Lit 2)) (Leaf "" (Lit 2))
另外,请注意上面关于数据定义的
派生
条款,特别是
Ord
;这会告诉编译器自动为该类型的值创建排序关系。这使您可以一致地对它们进行排序,这意味着您可以,例如,在子表达式上定义规范顺序,以便在重新排列交换操作时,您不会陷入循环中。给定一些规范化约化和规范化顺序的子表达式,在大多数情况下,您将能够使用
Eq
给出的自动相等关系来检查子表达式的等价性

请注意,标签将影响此处的顺序和相等性。如果不希望这样,您需要为
Eq
Ord
编写自己的定义,就像我为
Num
给出的定义一样

之后,您可以编写一些遍历和归约函数,以执行诸如应用运算符、执行变量替换等操作