Haskell-容器的容器和实例声明

Haskell-容器的容器和实例声明,haskell,Haskell,来自Haskell新手的简短版本:假设我有一个类容器,其中容器有*->*kind。我想将其放入另一个容器中,并使第二个容器成为原始类的实例,如中所示: data Container2 a container = Container2 (container a) instance Container (Conrainer2 a) where ... 但这似乎是不可能的,因为GHC总是产生以下错误: Kind mis-match The first argument of `Conta

来自Haskell新手的简短版本:假设我有一个类容器,其中容器有
*->*
kind。我想将其放入另一个容器中,并使第二个容器成为原始类的实例,如中所示:

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) }
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)'
我将实例声明更改为:

instance Iter (Iter iter => TransformedIter iter from) where
这产生了另一个错误:

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) }
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。但是这个扩展真的有必要吗?

答案在的评论中给出,现在我终于有了一个不使用任何GHC扩展的版本(我以前在实例声明中对上下文使用了错误的语法):


这将打印2 4 6 8 10

只需翻转参数,如
data Container2 container a=Container2(container a)
。当您有
实例Iter f
时,它预期您可以为元素
a
上的迭代器编写
fa
,而如果您有
类型f=TransformedIter from to
,则
fa
不是
a
元素上的迭代器,它是从内部迭代器
a
元素的迭代器。此外,该类在Haskell中已作为
可折叠的
存在。特别是,任何
Foldable t
都有
toList::ta->[a]
,可以让您构建迭代器。谢谢@J.Abrahamson,我理解了类型排序的错误。但我现在遇到了另一个错误,请参阅更新版本。请尝试
实例Iter Iter=>Iter(TransformedIter Iter from),其中
:首先是约束条件。如果您的问题得到解决,适当的做法是为您自己的问题添加答案(并继续接受),而不是修改问题以包含答案。这样,未来的访问者一眼就能知道问题从哪里结束,解决方案从哪里开始!=)