2010-08-06 88 views
2

我在Haskell中玩耍试图获得它的挂钩。我遇到了我的类型类问题。我想要做的是通过定义类和方法来创建一个通用的a *模块,然后我试图在程序中使用它们。我的问题是,当我试图让我的专栏的数据类型我的董事会类的一个实例的列表(代表地图),我发现了以下错误:自定义类型和类的实例列表

Illegal instance declaration for `Board [Box]' 
    (All instance types must be of the form (T a1 ... an) 
    where a1 ... an are type *variables*, 
    and each type variable appears at most once in the instance head. 
    Use -XFlexibleInstances if you want to disable this.) 
In the instance declaration for `Board [Box]' 

我一直在谷歌上搜索周围这是一个解决方案,但到目前为止,我只找到了一个描述解决方案的页面,我在这里无法理解:http://www.haskell.org/haskellwiki/List_instance。它描述了如何使用从上面的错误消息生成的XFlexibleInstances,但是,当我尝试使用列表的一个元素作为Box数据类型时,出现错误消息。

Couldn't match expected type `t' against inferred type `Box' 
    `t' is a rigid type variable bound by 
     the type signature for `!!' at <no location info> 

我不知道这是我做的一些奇怪的错误还是如果我的设计根本不是一个好的错误。相关的代码是在这里:

class Tile a where 
    tilePosition :: a -> (Int, Int) 
    tileStatus :: a -> Status 

董事会类应该是瓷砖的列表(或其中的一些集合)

class Board b where 
    surroundingTiles :: Tile t => b -> (Int, Int) -> [t] 
    startingPosition :: b -> Maybe (Int, Int) 
    targetPosition :: b -> Maybe (Int, Int) 
    (!!)    :: Tile t => b -> (Int, Int) -> Maybe t 

这似乎编译,但在另一个文件中,我尽量让这些类的实例是我得到的错误

instance Board [Box] where 
    boxes !! pos = foldl (\acc b -> if boardPos b == pos then Just b else acc) Nothing boxes 
    ... 

任何提示在正确的方向将不胜感激。

回答

1

对于[Box]功能!!类型必须Tile t => [Box] -> (Int, Int) -> Maybe t,意为每种类型的t这是你需要能够得到一个t[Box]Tile一个实例。

但是,您的实施类型为[Box] -> (Int, Int) -> Maybe Box,这意味着您只能从[Box]中获得Box,因此不起作用。

,你可以做些什么来得到你想要的东西是这样的:

class Board b where 
    surroundingTiles :: Tile t => b t -> (Int, Int) -> [t] 
    startingPosition :: Tile t => b t -> Maybe (Int, Int) 
    targetPosition :: Tile t => b t -> Maybe (Int, Int) 
    (!!)    :: Tile t => b t -> (Int, Int) -> Maybe t 

instance Board [] where 
    ... 

这样,您就可以使用瓷砖作为董事会的任何实例的名单别的也委员会(名单,但你可以因为所有功能都需要t作为Tile的一个实例)。

如果你需要说“瓷砖的名单瓷砖的董事会”没有也使所有其他列表成板,则需要启用多参数的类型类,让你可以说这样的话:

class Tile t => Board b t where 
    surroundingTiles :: b t -> (Int, Int) -> [t] 
    startingPosition :: b t -> Maybe (Int, Int) 
    targetPosition :: b t -> Maybe (Int, Int) 
    (!!)    :: b t -> (Int, Int) -> Maybe t 

instance Board [Tile] Tile where 
    ... 
+0

哇,非常感谢您的详细解答。你给的第一个例子足以让我继续。 – Kuxi 2010-08-06 15:21:39