2012-10-02 79 views
5

我在努力学习Haskell,认为这将是实现Combinatorial Game Theory的完美语言。我在Python中做了一些这样的工作来教自己的OOP原则和运算符重载,但Haskell吸引我,因为它的语法看起来更加数学化,并且有一个我非常喜欢的数学背景。而且,懒惰地实施无限列表是相当了不起的。定义递归数据结构

不管怎么说,我迄今为止的是,编译,但我已经用它写的第一功能的数据结构给我:

Prelude> :l cgt 
[1 of 1] Compiling Main    (cgt.hs, interpreted) 

cgt.hs:8:30: 
    Couldn't match expected type `([Game], b0)' with actual type `Game' 
    In the first argument of `fst', namely `b' 
    In the second argument of `(:)', namely `(fst b)' 
    In the expression: a : (fst b) 
    Failed, modules loaded: none. 

这里是我的代码...

--A game that is Zero (base case) is two empties 
--Anything else must be two lists of games, a left list and a right list. 

data Game = Zero 
      | Position ([Game], [Game]) 

putL :: Game -> Game -> Game 
putL a b = Position (a :(fst b), snd b) 

我意识到游戏有点像Wikibook上讨论的树,但它们有其他限制。

  1. 的位置(亲属到树节点)可以有很多可能的行动
  2. 的位置可能只包含其他游戏
  3. 有一个特殊的游戏,零,即没有可能的行动。
  4. 所有游戏都是使用零建立的。

所以,当我写putL我说,“把一个游戏a和另一场比赛b,利弊ab的第一部分,并独自离开的b第二部分,返回的位置(这是一个一种游戏)“。至少,这正是我想要做的。相反,Haskell认为我返回的类型是([Game], b0),我不知道为什么。

谢谢!我感谢您的帮助。

回答

10

您不能在Game类型的东西上使用fstsnd函数。由于您尚未在数据构造函数ZeroPosition中为您的字段声明名称,实际访问它们的唯一方法是通过模式匹配。 (请注意,我也去掉了不必要的元组在Position构造函数)

data Game 
    = Zero 
    | Position [Game] [Game] 

putL :: Game -> Game -> Game 
putL game Zero = ??? 
putL game (Position games1 games2) = Position (game : games1) games2 

现在,我显然不知道要发生的Zero构造什么,所以你必须填写这些???“你自己。

+4

实际上,零和游戏已经被'位置[] []'表示,所以没有必要为这额外的构造函数。 – hammar

+0

我明白了。我使用了一个元组,因为我只想要两组位置,但这是不必要的,因为这两个列表是在数据结构中定义的。 而对于函数,您可以定义什么类型作为位置进入,返回我想要的。 –

6

dflemstr的回答是正确的。我要解释你得到的错误信息。

  • a : fst b必须有型号[Game] ---同意,是吗?
  • 因此a必须有类型Game ...(和它,万岁)
  • ...和fst b必须有类型[Game]
  • fst在一对作为输入,并产生所述一对的第一个元素,所以...
  • ...b必须有类型([Game], b0)(对于某些类型b0,我们还没有制定出来呢)(这是预期型)
  • 这是一个问题,因为根据对putL类型签名,b类型必须Game(这是实际型)---它不能是一对
+0

谢谢,这是更清晰! –