2013-10-19 151 views
0

来自Haskell新手的简短版本:假设我有一个Container容器,其中Container有* -> *种类。我希望把他们到另一个容器中,仍然使第二容器的原始类的实例像:Haskell - 容器和实例declration的容器

data Container2 a container = Container2 (container a) 

instance Container (Conrainer2 a) where ... 

但看来这是不可能的,因为GHC总是产生类似的错误:

Kind mis-match 

    The first argument of `Container' should have kind `* -> *', 
    but `Container2 a' has kind `(* -> *) -> *' 

是否可以解决这个问题?

长版:我用下面的代码建模Java中的迭代器接口玩弄:

module Main where 

data NextResult a iter = Stop | More a (iter a) 

class Iter iter where 
    next :: iter a -> NextResult a iter 

-- Convert iterator to a list 
toList :: (Iter c) => c a -> [a] 
toList iter = case next iter of 
    Stop -> [] 
    More value iter2 -> value : toList iter2 

-- List itself is iterator 
instance Iter [] where 
    next [] = Stop 
    next (x:xs) = More x xs 

main = let iter = [1,2,3,4,5] in print $ toList iter 

随着GHC 7.4.1本编译并打印预期1 2 3 4 5。现在我想定义一个从函数和迭代器构造新迭代器的变换迭代器。对于我添加了以下几行:

data TransformedIter from to iter = TransformedIter (from->to) (iter from) 

instance Iter (TransformedIter from to) where 
    next (TransformedIter f iter) = case next iter of 
    Stop -> Stop 
    More value iter2 -> More (f value) (TransformedIter f iter2) 

但生成该错误:

Main.hs:21:16: 
    Kind mis-match 
    The first argument of `Iter' should have kind `* -> *', 
    but `TransformedIter from to' has kind `(* -> *) -> *' 
    In the instance declaration for `Iter (TransformedIter from to)' 

我想变通方法,但结果总是一种或另一种类型错误。那么如何在Haskell中对这种转换进行建模呢?

更新

我误解了实例声明的工作原理。根据该建议,下面我翻TransformedIter类型的顺序,并结束了:

module Main where 

data NextResult a iter = Stop | More a (iter a) 

class Iter iter where 
    next :: iter a -> NextResult a iter 

toList :: (Iter c) => c a -> [a] 
toList iter = case next iter of 
    Stop -> [] 
    More value iter2 -> value : toList iter2 

instance Iter [] where 
    next [] = Stop 
    next (x:xs) = More x xs 

main = let iter = [1,2,3,4,5] in print $ toList iter 

data TransformedIter iter from to = TransformedIter (from->to) (iter from) 

instance Iter (TransformedIter iter from) where 
    next (TransformedIter f iter) = case next iter of 
    Stop -> Stop 
    More value iter2 -> More (f value) (TransformedIter f iter2) 

但是所产生另一个错误:

Main.hs:22:40: 
    No instance for (Iter iter) 
     arising from a use of `next' 
    In the expression: next iter 
    In the expression: 
     case next iter of { 
     Stop -> Stop 
     More value iter2 -> More (f value) (TransformedIter f iter2) } 
    In an equation for `next': 
     next (TransformedIter f iter) 
      = case next iter of { 
       Stop -> Stop 
       More value iter2 -> More (f value) (TransformedIter f iter2) } 

我改变了实例声明:

instance Iter (Iter iter => TransformedIter iter from) where 

这产生了另一个错误:

Main.hs:21:10: 
    Illegal instance declaration for `Iter 
             (Iter iter => TransformedIter iter from)' 
     (All instance types must be of the form (T a1 ... an) 
     where a1 ... an are *distinct 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 `Iter (Iter iter => 
              TransformedIter iter from)' 
我加-XFlexibleInstances

后,我得到了:

Main.hs:21:10: 
    Illegal polymorphic or qualified type: 
     Iter iter => TransformedIter iter from 
    In the instance declaration for `Iter (Iter iter => 
              TransformedIter iter from)' 

所以我还没有看到如何声明TransformedIter是Iter项目的一个实例。任何线索?

更新2

使用GADTs GHC扩展我设法确定TransformedIter:

module Main where 

data NextResult a iter = Stop | More a (iter a) 

class Iter iter where 
    next :: iter a -> NextResult a iter 

toList :: (Iter c) => c a -> [a] 
toList iter = case next iter of 
    Stop -> [] 
    More value iter2 -> value : toList iter2 

instance Iter [] where 
    next [] = Stop 
    next (x:xs) = More x xs 

data TransformedIter iter from to where 
    TransformedIter :: Iter iter => 
        (from->to) -> (iter from) -> TransformedIter iter from to 

instance Iter (TransformedIter iter from) where 
    next (TransformedIter f iter) = case next iter of 
    Stop -> Stop 
    More value iter2 -> More (f value) (TransformedIter f iter2) 

twice = (*) 2 

main = let iter = TransformedIter twice [1,2,3,4,5] in print $ toList iter 

,编译并打印预期的2 4 6 8 10,但确实需要这种扩展?

+0

只需翻转像'data Container2 container a = Container2(container a)'这样的参数即可。当你有'instance Iter f'时,它预计你可以为元素'a'的迭代器写'fa',而如果你有'type F = TransformedIter from',那么'F a'不是元素的迭代器的'a',它是内部迭代器'a'的元素'to'的迭代器。 –

+0

另外,这个类在Haskell中已经存在为'Foldable'。特别是,任何'Foldable t'都有'toList :: t a - > [a]',它可以让你构建你的迭代器。 –

+0

谢谢@J。 Abrahamson,我明白类型排序有什么问题。但是现在我又遇到了另一个错误,请参阅更新后的版本。 –

回答

1

答案被J. Abrahamson在评论中给出的,现在我终于在不使用任何GHC扩展(我用错了语法方面的实例声明先前)工作的版本:

module Main where 

data NextResult a iter = Stop | More a (iter a) 

class Iter iter where 
    next :: iter a -> NextResult a iter 

toList :: (Iter c) => c a -> [a] 
toList iter = case next iter of 
    Stop -> [] 
    More value iter2 -> value : toList iter2 

instance Iter [] where 
    next [] = Stop 
    next (x:xs) = More x xs 

data TransformedIter iter from to = TransformedIter (from->to) (iter from) 

instance Iter iter => Iter (TransformedIter iter from) where 
    next (TransformedIter f iter) = case next iter of 
    Stop -> Stop 
    More value iter2 -> More (f value) (TransformedIter f iter2) 

twice = (*) 2 

main = let iter = TransformedIter twice [1,2,3,4,5] in print $ toList iter 

,打印2 4 6 8 10