2012-05-03 3 views
7

(恐ろしく不自然な例を言い訳してください)"where"句に式ジェネリック型を与えるにはどうすればよいですか?私が何をしたいか

は、WHERE句でタイプを指定します:

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

しかし、これはエラーが発生します。

*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. 

具体的な型を指定する場合、aとにはIntを代入しますbについて、何の問題:

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

だから私の質問はありません:どのように私は、WHERE句でジェネリック型と型制約を指定するのですか? where句インサイド

答えて

15

、型変数ab新しい型の変数です。どの型シグネチャもトップレベルで定義されているかのように新しい型を持っています。

あなたはScopedTypeVariables拡張子(ファイルの先頭に{-# LANGUAGE ScopedTypeVariables #-}を置く)をオンにし、にsomemapの型宣言を変更した場合:

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

、あなたが指定したwhere句の定義が正しく動作します。 forallは下位互換性のためにのみ必要なものだと思うので、多態性値の型変数をwhere節に再利用するコードは壊れません。

拡張子を使用したくない場合は、醜いヘルパー関数を定義して、asTypeOfのような型を統一することもできます。

+1

http://stackoverflow.com/questions/7408911/haskell-magical-code-whats-going-on-hereのコードは、このような「醜いヘルパー機能」から生じる可能性のある混乱の良い例です。 –

関連する問題