5

以下を実行できる関数を定義するために、いくつかの GHC 拡張機能で遊んでいます。

let a = A :: A  -- Show A
    b = B :: B  -- Show B
  in
    myFunc show a b -- This should return (String, String)

myFuncは、 の署名で完全にポリモーフィックである必要がありshowます。abShow

GHC拡張機能RankNTypes, ConstraintKinds,を使った私の試みは次のKindSignaturesとおりです:

myFunc :: forall (k :: * -> Constraint) a b d. (k a, k b) 
            => (forall c. k c => c -> d) -> a -> b -> (d, d)

私の主な目的は、これらの拡張機能がどのように機能するかを理解することです。kしかし、私の目には、 someaとを満たす制約があり、満たす任意の型を取り、特定の を返すことができるb関数もあるとGHCに伝えているように見えます。今、これらの条件下で、関数を適用したいタプルを取得する(forall c. k c => c -> d)ckdab(d,d)

GHC が不平を言う方法は次のとおりです。

Could not deduce (k0 a, k0 b)
from the context (k a, k b)
  bound by the type signature for
             myFunc :: (k a, k b) =>
                       (forall c. k c => c -> d) -> a -> b -> (d, d)
  at app/Main.hs:(15,11)-(16,56)
In the ambiguity check for the type signature for ‘myFunc’:
  myFunc :: forall (k :: * -> Constraint) a b d.
            (k a, k b) =>
            (forall c. k c => c -> d) -> a -> b -> (d, d)
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature for ‘myFunc’:
  myFunc :: forall (k :: * -> Constraint) a b d. (k a, k b) =>
            (forall c. k c => c -> d) -> a -> b -> (d, d)

...

Could not deduce (k c)
from the context (k a, k b)
  bound by the type signature for
             myFunc :: (k a, k b) =>
                       (forall c. k c => c -> d) -> a -> b -> (d, d)
  at app/Main.hs:(15,11)-(16,56)
or from (k0 c)
  bound by the type signature for myFunc :: k0 c => c -> d
  at app/Main.hs:(15,11)-(16,56)
In the ambiguity check for the type signature for ‘myFunc’:
  myFunc :: forall (k :: * -> Constraint) a b d.
            (k a, k b) =>
            (forall c. k c => c -> d) -> a -> b -> (d, d)
To defer the ambiguity check to use sites, enable AllowAmbiguousTypes
In the type signature for ‘myFunc’:
  myFunc :: forall (k :: * -> Constraint) a b d. (k a, k b) =>
            (forall c. k c => c -> d) -> a -> b -> (d, d)
app/Main.hs15:40

私は何が欠けていますか?

4

1 に答える 1

5

問題は、関数(forall c . k c => c -> d)を引数として渡すだけでは、型チェッカーがk実際に何であるかを明確に判断するには不十分なことです。forall制約を明示的に渡すと機能し、外部または明示的な種類は必要ありません。

import Data.Proxy

myFunc :: (k a, k b) => Proxy k -> (forall c. k c => c -> d) -> a -> b -> (d, d)
myFunc _ f a b = (f a, f b)

その後

let (c, d) = myFunc (Proxy :: Proxy Show) show a b
于 2016-09-22T10:11:33.883 に答える