Написание функции, полиморфной в семействе типов

Вчера я экспериментировал с семействами типов и наткнулся на препятствие со следующим кодом:

  {-# LANGUAGE TypeFamilies #-}

  class C a where
      type A a
      myLength :: A a -> Int

  instance C String where
      type A String = [String]
      myLength = length

  instance C Int where
      type A Int = [Int]
      myLength = length

  main = let a1 = [1,2,3]
             a2 = ["hello","world"]
         in print (myLength a1)
            >> print (myLength a2)

Здесь у меня есть тип, связанный с классом C и функция, вычисляющая длину связанного типа. Однако приведенный выше код дает мне эту ошибку:

 /tmp/type-families.hs:18:30:
     Couldn't match type `A a1' with `[a]'
     In the first argument of `myLength', namely `a1'
     In the first argument of `print', namely `(myLength a1)'
     In the first argument of `(>>)', namely `print (myLength a1)'
 /tmp/type-families.hs:19:30:
     Couldn't match type `A a2' with `[[Char]]'
     In the first argument of `myLength', namely `a2'
     In the first argument of `print', namely `(myLength a2)'
     In the second argument of `(>>)', namely `print (myLength a2)'
 Failed, modules loaded: none.

Однако если я изменю "тип" на "данные", код компилируется и работает:

  {-# LANGUAGE TypeFamilies #-}

  class C a where
      data A a
      myLength :: A a -> Int

  instance C String where
      data A String = S [String]
      myLength (S a) = length a

  instance C Int where
      data A Int = I [Int]
      myLength (I a) = length a

  main = let a1 = I [1,2,3]
             a2 = S ["hello","world"]
             in
               print (myLength a1) >>
               print (myLength a2)

Почему "длина" не работает должным образом в первом случае? Строки «type A String ...» и «type A Int ...» указывают, что тип «A a» является списком, поэтому myLength должен иметь следующие типы соответственно: «myLength :: [String] -> Int» или "myLength :: [Int] -> Int".

13
задан Community 12 July 2011 в 15:06
поделиться