2016-06-30 15 views
0

ここでは簡単な例を示します。型クラスの例では、私はそれがでコンパイルに失敗しforallなしの関数定義の間、明示的forallを言わなければならない理由、私は疑問に思う:型クラスメソッドのスコープ付き型変数とスタンドアロン関数の比較

Couldn't match kind ‘Nat’ with ‘*’ 
    When matching types 
     proxy0 :: Nat -> * 
     Proxy :: * -> * 
    Expected type: proxy0 n0 
     Actual type: Proxy p0 
    In the first argument of ‘natVal’, namely ‘(Proxy :: Proxy p)’ 
    In the second argument of ‘($)’, namely ‘natVal (Proxy :: Proxy p)’ 
    In the first argument of ‘(++)’, namely 
     ‘(show $ natVal (Proxy :: Proxy p))’ 

コード:

{-# LANGUAGE DataKinds   #-} 
{-# LANGUAGE KindSignatures  #-} 
{-# LANGUAGE RankNTypes   #-} 
{-# LANGUAGE RoleAnnotations  #-} 
{-# LANGUAGE ScopedTypeVariables #-} 
{-# LANGUAGE TypeOperators  #-} 
{-# LANGUAGE TypeFamilies  #-} 

data Container (p :: Nat) (k :: Nat) = Container { first :: [Int], second :: [Int] } 

instance (KnownNat p, KnownNat k) => Show (Container p k) where 
    show c = "Container " ++ (show $ natVal (Proxy :: Proxy p)) ++ 
        " " ++ (show $ natVal (Proxy :: Proxy k)) 

showMe :: forall p k . (KnownNat p, KnownNat k) => Container p k -> String 
showMe c = "Container " ++ (show $ natVal (Proxy :: Proxy p)) ++ 
        " " ++ (show $ natVal (Proxy :: Proxy k)) 

答えて

5

ScopedTypeVariablesインスタンスヘッド内の変数を入力します明示的なforallなしでインスタンス本体のスコープに入れます。これは型シグニチャでは起こりません。代わりに、showMeの定義でpkを範囲に含めるにはforallを使用する必要があります。

関連する問題