2012-02-05 18 views
4

我正在做一個有趣的項目,我試圖從Java中重做一些基本數據類型和概念。目前我正在處理迭代器。在Haskell中返回其他類型的類B中的某些東西

我的方法如下: (1)翻譯接口到類型類 (2)聲明的自定義數據類型和實例對於實際的實現

因此,我創建以下類型的類:

class Iterator it where 
    next :: it e -> (it e, e) 
    hasNext :: it e -> Bool 

class Iterable i where 
    iterator :: Iterator it => i e -> it e 

class Iterable c => Collection c where 
    add :: c e -> e -> c e 

是的,我試圖翻譯迭代器的概念(在這種情況下,它只是實際列表中的一個框)。

這是我實現一個簡單的列表:

data LinkedList e = Element e (LinkedList e) | Nil 
    deriving (Show, Eq) 

instance Collection LinkedList where 
    add Nil e = Element e Nil 
    add (Element x xs) e = Element x $ add xs e 

我已經排除像刪除等功能,包含,爲的addAll簡化。

這裏是Iterator:

data LinkedListIterator e = It (LinkedList e) 

instance Iterator LinkedListIterator where 
    hasNext (It Nil) = False 
    hasNext (It _) = True 
    next (It (Element x xs)) = (It xs, x) 

最後,可迭代LinkedList的一個實例丟失。這是我做的:

instance Iterable LinkedList where 
    iterator list = It list 

迭代器功能包裝列表爲LinkedListIterator,並返回。這裏GHC聲稱有錯誤:

Could not deduce (it ~ LinkedListIterator) 
from the context (Iterator it) 
    bound by the type signature for 
      iterator :: Iterator it => LinkedList e -> it e 

    `it' is a rigid type variable bound by 
     the type signature for 
     iterator :: Iterator it => LinkedList e -> it e 

Expected type: it e 
    Actual type: LinkedListIterator e 

我不太明白。 LinkedListIterator有一個Iterator的實例,爲什麼期望的類型「it e」與實際的類型「LinkedListIterator e」不兼容(據我所知,是迭代器e)。無論如何,代字號(~)的意思是什麼?什麼是剛性類型變量?

編輯:我改變了標題從Translating Java Types into Haskell types: type deduction fail due to rigid type variableReturning something from another type class B in function of type class A in Haskell,因爲我相信我的實際問題在涉及到返回的東西-的型類-B-從型類-A-問題迭代器的功能。

SOLUTION:感謝我的答案,我現在將我的代碼更改爲以下版本。但是,我讀了Typeclassopedia,並且只能推薦它。正如所說的,應該學習haskell成語。

data Iterator c e = Next (Iterator c e, e) | Empty 
    deriving (Show, Eq) 

next :: Iterator c e -> (Iterator c e, e) 
next (Next (i, e)) = (i, e) 

hasNext :: Iterator c e -> Bool 
hasNext Empty = False 
hasNext _ = True 

class Iterable i where 
    iterator :: i e -> Iterator (i e) e 

instance Iterable LinkedList where 
    iterator Nil = Empty 
    iterator (Element x xs) = Next (iterator xs, x) 

回答

8
iterator :: Iterator it => i e -> it e 

這意味着主叫可以選擇it是任何他們想要的,受它實現Iterator。看着它的另一種方式是它是承諾iterator爲所有類型it工作,實現Iterator

無論呼叫者要求什麼,您的實施都會提供LinkedListIterator

編譯器無法證明它們是相同的東西(因爲調用者可能會要求不同的Iterator實現),所以會發出錯誤。

這不同於Java,調用者在其中選擇輸入的類,被調用者選擇輸出的類。在Haskell中,調用者選擇輸入的輸出類型。

~表示類型相等。


一些更廣泛的觀點。 (我明白,你想的Java成語翻譯成哈斯克爾,但海事組織你需要學習Haskell的成語。)

  1. 有時候你不想返回實現類型類的值,你只是想返回一個值。

    如果相反的Iterator是一個類型類,它是一個數據類型...

    data Iterator e = Iterator {next :: (Iterator e, e), 
              hasNext :: Bool} 
    

    ...那麼你可以只返回Iterator類型的值,而不必擔心不同類型類的實現。

    懶惰意味着迭代器中的連續值不會被生成(並且異常不會被拋出),直到被要求爲止。只要你還沒有老的迭代器值,這些值可以在迭代時被垃圾收集,所以我們仍然使用恆定空間。

  2. Iterator更好的定義是

    data Iterator e = Iterator {next :: Maybe (Iterator e, e)} 
    

    這是更好,因爲它使你更難,要求從迭代器的下一個值,而不先檢查,看看有下一個值。

  3. 我的Iterator的第二個定義看起來有點像你的LinkedList的定義,也像標準Haskell列表(它們本身就是鏈表)的定義。事實上,將Haskell列表用作迭代所需的中間數據結構是習慣用法。

  4. 閱讀關於Typeclassopedia中的FoldableTraversable類型類。實際上,read the Typeclassopedia,這是對一些更可怕的類型類的一個很好的介紹。

+1

好的答案 - Iterator類可以添加一個關聯的類型,所以LinkedLists總是使用LinkedListIterator(儘管這會讓我們進入高級領域)。 – 2012-02-05 11:58:14

+0

這是另一種思考這個問題的方法。 Java的子類型多態對應於存在類型。如果我有一個返回類型爲'Iterator'的方法,我所說的是「這個函數可以返回一個* some *類型的值'T',它是'Iterator'的子類型。」在Haskell中,我改爲有一個普遍量化的類型; 'Iterator it => ... - > it'意思是「這個函數可以返回任何*類型't'的值,它是'Iterator'的一個實例。」 – 2012-02-05 16:19:51

相關問題