首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Haskell -容器容器和实例解密

Haskell -容器容器和实例解密
EN

Stack Overflow用户
提问于 2013-10-19 18:43:16
回答 1查看 165关注 0票数 0

Haskell新手的简短版本:假设我有一个容器类,容器中包含* -> *类。我希望将其放入另一个容器中,并仍然将第二个容器作为原始类的实例,如

代码语言:javascript
复制
data Container2 a container = Container2 (container a)

instance Container (Conrainer2 a) where ...

但这似乎是不可能的,因为GHC总是生成以下错误:

代码语言:javascript
复制
Kind mis-match

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

有可能解决这个问题吗?

长版本:我正在使用以下代码对Java中的迭代器接口建模:

代码语言:javascript
复制
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

使用GHC7.4.1,它编译并打印预期的1 2 3 4 5。现在,我想定义一个转换迭代器,它从一个函数和一个迭代器构建一个新的迭代器。为此,我增加了以下几行:

代码语言:javascript
复制
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)

但这产生了错误:

代码语言:javascript
复制
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类型的顺序,最后得到了:

代码语言:javascript
复制
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)

然而,这又产生了另一个错误:

代码语言:javascript
复制
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) }

我将实例声明更改为:

代码语言:javascript
复制
instance Iter (Iter iter => TransformedIter iter from) where

这产生了另一个错误:

代码语言:javascript
复制
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之后,我得到了:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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,但这个扩展真的需要吗?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2014-11-21 22:15:00

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

代码语言:javascript
复制
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

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/19469661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档