2016-12-21 11 views
2

私は、学習の練習としてハスケルに簡単なツールを書こうとしていて、わからないものに遭遇しました。ここにそれを示す簡単なサンプルがあります。関数の定義と型をハスケルで理解する

idMap :: a -> a 
idMap x = map id x 

main = do 
    print $ idMap [1, 2] 

私の理解によれば、この例では、実行時に[1, 2]をコンパイルして印刷する必要があります。しかし、次のメッセージでコンパイルに失敗した場合:それは一種の意味が

source_file.hs:2:18: error: 
    • Couldn't match expected type ‘[b0]’ with actual type ‘a’ 
     ‘a’ is a rigid type variable bound by 
     the type signature for: 
      idMap :: forall a. a -> a 
     at source_file.hs:1:10 
    • In the second argument of ‘map’, namely ‘x’ 
     In the expression: map id x 
     In an equation for ‘idMap’: idMap x = map id x 
    • Relevant bindings include 
     x :: a 
      (bound at source_file.hs:2:7) 
     idMap :: a -> a 
      (bound at source_file.hs:2:1) 

mapの署名が(a -> b) -> [a] -> [b]であることを考えるので、入力タイプは、必ずしも出力型と同じではなく、の署名ida -> aなので、確かにmap id(a -> a) -> [a] -> [a]の署名を持っていますか?

私が実際に理解していない第2の部分は、すべてのタイプ(上記のab)がIntegerであることを考えると、これが例外である理由です。 idMapの署名がa -> aであるので、出力タイプが入力タイプと異なることが予想される状況で使用される場合は、コンパイル例外のみが存在するはずです。

最後に、このコードを実際にどのように動作させるのですか?私の実際のコードはもう少し複雑で、出力タイプはコード内の他の場所での入力タイプと一致していますので、idMapのシグネチャを変更したくない場合は、何を書き込む必要があるかを知りたいその署名付きの関数です。

+2

'map id 'の型は' a - > [a] 'ですが、' a - > a'と指定します。 – Lee

答えて

6

idMapをリストに追加しています。したがって、引数の型はリスト型でなければなりません。さらに、戻り値の型はリスト([1,2])であると期待しているので、戻り値の型もリストでなければなりません。 id関数は完全多型(a -> a)なので、mapを任意のタイプのリストaにリストし、同じタイプのアイテムのリストを返しますa。したがって、最終的な型署名は[a] -> [a]でなければなりません。あなたの2番目の質問については

、それは引数の型と戻り値の型が両方とも同じであることは事実だが、a -> aなどタイプはすべてタイプaのために真ではありません。 mapのタイプシグネチャに基づいて、idMapは、にリスト引数を受け入れる必要があります。必要以上に拘束されている関数の型シグニチャを宣言することはできますが、それ以下ではありません。

3

idMap ...

idMap x = map id x 

の実装では... xmap idを適用することを含みます。結果として、xはリストでなければなりません。

GHCi> :t map id 
map id :: [b] -> [b] 

これはうまく動作します:あなたは予想通り、idxidMap xの使用のおかげで、(その要素がそうであるように)同じ型を持っているん

idMap :: [a] -> [a] 
idMap x = map id x 

注こと。

+0

ありがとうございます。それは意味をなさない。しかし、それは私がいつも署名で可能な限り明確にする必要があるということですか?私は 'a'は未知の型を意味し、別の未知の型のリストであると考えたでしょうか? – aquavitae

+1

型シグネチャ「a - > a」は、 'a'が* any *型である可能性があることを意味しますが、' map'の型シグネチャに基づいて、これは真ではありません。これは、あなたが理解するのを助けるかもしれません:http://stackoverflow.com/questions/12230820/haskell-example-of-function-of-type-a-b-the-identity – mnoronha

+1

@aquavitae問題は、mnoronhaが指摘するように、 'idMap :: a - > a'は、あなたの関数に何かを渡すことができるということを意味します(たとえ、' Integer'や 'Bool'など)。これは真実ではありません。どのように 'map'を使っているかを考えると、' [a] - > [a] 'は可能な最も一般的な型です(型検査によって受け入れられるより特殊なシグニチャの例は' idMap :: [Integer] > [整数] ')。 – duplode

関連する問題