2

これは本当に単純なはずですが、私はそれを回避できないようです。

独自の List クラスがあり、そのインターフェイスでheadandを宣言しているとします。これは同種のアイテムのコレクションです。次に、インターフェイスを実装する型を作成します。tailListdataList

次のコードは私が思いついたものですが、動作しません: どうすれば修正できますか?

class List l where                                                             
    head :: l -> a  -- ERROR! How do I tell: given a list, return an element?                                                      
    tail :: l -> l                                                             

data ConsList a = Nil | Cons a (ConsList a)                                    

instance List (ConsList Int) where                                             
    head Nil = error "Empty List"                                              
    head (Cons h _) = h                                                        
    tail Nil = error "Empty List"                                              
    tail (Cons _ t) = t                       

前もって感謝します!

4

3 に答える 3

12

List型クラスを定義するのではなく、コンストラクタークラスとして定義します。

class List l where
    head :: l a -> a
    tail :: l a -> l a                                        

data ConsList a = Nil | Cons a (ConsList a)

instance List ConsList where
    head Nil = error "Empty List"
    head (Cons h _) = h
    tail Nil = error "Empty List"
    tail (Cons _ t) = t

または、要素の型を修正します (注: type のConsList場合、これには柔軟なインスタンスが必要です)。

{-# LANGUAGE FlexibleInstances #-}

class List l where
    head :: l -> Int
    tail :: l -> l

data ConsList a = Nil | Cons a (ConsList a)

instance List (ConsList Int) where
    head Nil = error "Empty List"
    head (Cons h _) = h
    tail Nil = error "Empty List"
    tail (Cons _ t) = t

最後に、型ファミリを使用すると、さらに凝ったことを行うことができますが、そこまで行く必要があるかどうかは、実際には特定のシナリオに依存します (おそらくそうではない):

{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies      #-}

class List l where
    type Elt l
    head :: l -> Elt l
    tail :: l -> l

data ConsList a = Nil | Cons a (ConsList a)

instance List (ConsList Int) where
    type Elt (ConsList Int) = Int

    head Nil = error "Empty List"
    head (Cons h _) = h

    tail Nil = error "Empty List"
    tail (Cons _ t) = t
于 2012-07-10T14:29:57.153 に答える
7

あなたはできる

  • コンストラクタクラスにして、

    class List l where
        head :: l a -> a
        tail :: l a -> l a
    
  • 関数の依存関係を持つマルチパラメーター型クラスにする

    class List l a | l -> a where
        head :: l -> a
        tail :: l -> l
    
  • 型ファミリーを使用する

    class List l where
        type Elem l
        head :: l -> Elem l
        tail :: l -> l
    

コンストラクタークラスが最善の方法だと思います。

于 2012-07-10T14:33:49.507 に答える
3

リストを抽象化する最も簡単な方法は、型コンストラクターを抽象化することです。つまり、over[]ではなくover [a](の構文上のシュガー[] a)です。

したがって、クラスは次のようになります。

class List l where
  head :: l a -> a  -- now l is applied to the element type
  tail :: l a -> l a

次に、インスタンスはそれに応じて変更されます。

instance List ConsList where
  ...  -- code as before
于 2012-07-10T14:31:01.207 に答える