2016-05-03 5 views
3

私はHaskellで説明できない振る舞いを見つけました。私は、ReaderT Monadで使用したいレコードタイプに多相関数を格納しようとしています。私がasksで自分の関数を取得すると、コンパイラはそれを多相として認識せず、関数の最初の出現時に型を修正するようです。レコード型の多態関数Haskell

runReaderT (ask 
      >>= \(Test f) -> (liftIO . putStrLn $ show (f 2 :: Int))  
          >> (liftIO . putStrLn $ show (f "hello")) 
      ) (Test id) 

だからそれは何かである:これを実行しようとすると

{-# LANGUAGE Rank2Types    #-} 

data Test = Test {f :: (forall a. a -> a)} 

runReaderT (asks f 
      >>= \f -> (liftIO . putStrLn $ show (f 2 :: Int)) 
        >> (liftIO . putStrLn $ show (f "hello")) 
      ) (Test id) 

は、私が手::

Couldn't match expected type ‘Int’ with actual type ‘[Char]’ 
In the first argument of ‘f’, namely ‘"hello"’ 
In the first argument of ‘show’, namely ‘(f "hello")’ 
In the second argument of ‘($)’, namely ‘show (f "hello")’ 

ただし、次のコードは動作します私はGHCiの中で、この最小限の例を作成しましたasksで特別?私はこれに関するアドバイスに感謝しています。

+0

で、私はそれが私が間違っていない場合は、ラムダ引数はあなたがない限り、まだ単相です\後に現れる 'F'に関係していると思うようにそれはまた、明示的にタイプを与えるために働く必要がありますそれ以外の場合は – Ingo

+1

ちょうどいいね!Rank2Typesは、RankNTypesにエイリアスされた廃止された拡張です。 (そして、RankNTypesは 'forall'sだけを書くことができます.Ingoの答えの詳細として、GHCで上位ランクの型推論はありません。) – hao

答えて

4

前回私がチェックしたとき、GHCは上位ランクのタイプを推測できませんでした。したがって、あなたがいるとき

\f -> ... f x .... f y 

fは決して多形性ではありません。

上位のランクフィールドを宣言しているパターンと、注釈付きの関数のLHSの中で、型推論が上位ランクの型を認識するように、変数の型が非常に明白なのは2つの場所だけです。

\(f :: forall a.a -> a) -> .... f x ... f y 
+0

素早く答えてくれてありがとう!これはそれを説明します。だから、\(Test f) - >のマッチングはあなたが言及した最初のケ​​ースですよね? –

+0

まあ、それがうまくいった理由です。 – Ingo