2013-10-19 148 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