2012-05-03 19 views
7

(lütfen bağışlayın korkunç yapmacık örnek)Bir "where" deyiminde genel türleri nasıl ifade edebilirim?

Ne yapmak istediğiniz yeri-fıkrada türlerini belirtmek geçerli:

somemap :: (a -> b) -> [a] -> [b] 
somemap f xs = ys 
    where 
    some = take 5 xs :: [a] 
    ys = map f some :: [b] 

Ama bu hataya neden oluyor:

*Main> :load file.hs 
[1 of 1] Compiling Main    (file.hs, interpreted) 

fil.hs:15:18: 
    Couldn't match expected type `a1' against inferred type `a' 
     `a1' is a rigid type variable bound by 
      an expression type signature at file.hs:15:25 
     `a' is a rigid type variable bound by 
      the type signature for `somemap' at file.hs:12:12 
     Expected type: [a1] 
     Inferred type: [a] 
    In the second argument of `take', namely `xs' 
    In the expression: take 5 xs :: [a] 

file.hs:16:13: 
    Couldn't match expected type `b1' against inferred type `b' 
     `b1' is a rigid type variable bound by 
      an expression type signature at file.hs:16:24 
     `b' is a rigid type variable bound by 
      the type signature for `somemap' at file.hs:12:17 
    In the first argument of `map', namely `f' 
    In the expression: map f some :: [b] 
    In the definition of `ys': ys = map f some :: [b] 
Failed, modules loaded: none. 

Sadece beton tiplerini belirtiyorsam yerine a ve için 335.453.210, hiçbir sorun: Benim soru

somemap :: (Int -> Bool) -> [Int] -> [Bool] 
somemap f xs = ys 
    where 
    some = take 5 xs :: [Int] 
    ys = map f some :: [Bool] 

olduğunu

: nasıl jenerik türlerini belirlemek ve nerede-fıkrada kısıtlamaları yazabilirim? where maddesi içinde

cevap

15

, tip değişkenler a ve byeni tip değişkenler; tür değişkenler kapsam dışıdır, bu nedenle her tip imzanın yeni bir kaynağı vardır, tıpkı en üst düzeyde tanımlanmış gibi.

Eğer ScopedTypeVariables uzantısı açarsanız (dosyanızın üst kısmında {-# LANGUAGE ScopedTypeVariables #-} koymak) ve karşı somemap 'ın tür bildirimini değiştirin:

somemap :: forall a b. (a -> b) -> [a] -> [b] 

sonra belirtilen where fıkra tanımları düzgün çalışacaktır. Ben forall s sadece geriye doğru uyumluluk için gerekli olduğunu düşünüyorum, bu nedenle, where türündeki polimorfik değerler için tür değişkenlerini yeniden kullanan kod kırılmaz.

Bir uzantı kullanmak istemiyorsanız, alternatif, asTypeOf gibi türleri birleştirmek için çirkin yardımcı işlevleri tanımlamaktır.

+1

http://stackoverflow.com/questions/7408911/haskell-magical-code-whats-going-on-here adresindeki kod, bu tür "çirkin yardımcı işlevlerden" kaynaklanan karışıklığa iyi bir örnektir. –

İlgili konular