スコーレムとは?
存在記号変数IEは、「外界は知ることができないが、内界は知ることができる、剛体/具体的なタイプを持っている」。
では、Skolemsをどのように使用しますか?
TL; DR
unwrapBroken (ExistentiallyTyped x) = x
unwrapOk (ExistentiallyTyped x) = useConstraint x
Skolemは、気になるタイプクラスのインスタンスがある場合に役立ちます。アンラップされたものは、その制約を介して(のみ?)使用できます。
簡潔にするために、ここにエスケープするスコーレム(a
内のforall a. ExistentiallyTyped a
)があります:
data ExistentiallyTyped = forall a. SomeConstraint a => ExistentiallyTyped a
unwrapBroken :: forall a. ExistentiallyTyped -> a <---- what? how'd that `a` break out? not the same `a` as in ExistentiallyTyped
unwrapBroken (ExistentiallyTyped x) = x :: a <---- not the same `a` as above!
あなたはそれをすることはできません、それa
はラッピングx :: a
内で定量化されていますが、ライン上でExistentiallyTyped
考えてください。今ではどういうわけか全称記号化されていますか?!(注意、これは依存型で可能になり始めていると思いますが、haskellにはまだありません...)。つまり、この関数はまたはを返すことができると私に言っていますか?a
unwrapBroken :: forall a. ...
Int
String
AnyFrigginThing
いいえ。ただし、その制約を介してそれを利用できます。x :: a
unwrapOk :: ExistentiallyTyped -> ResultOfUseConstraint
unwrapOk (ExistentiallyTyped x) = useConstraint x
たとえば、ある型クラスを共有する型のリストが必要な場合は、これを利用しました。
notPossible :: HasBork a => [Proxy a]
notPossible = [Proxy @Thing1, Proxy @Thing2]
-- Error! expected a `Proxy a` but got a `Proxy Thing1`
代わりに:
data Borkable = forall a. HasBork a => Borkable a
borks :: [Borkable]
borks = [thing1, thing2]
later = useBork <$> borks