假设我有幻影类型
newtype Modulus s a = Modulus a deriving (Eq, Show)
强迫多态性的应用程序
withModulus ∷ a → (∀ s. Modulus s a → w ) → w
withModulus a k = k (Modulus a)
其中我使用了引入的类型变量s
,在其他类型中,强制它们共享索引s
newtype M s a = M a deriving (Eq, Show)
对于Modulus
和M
add :: Integral a ⇒ Modulus s a → M s a → M s a → M s a
add (Modulus m) (M a) (M b) = M (mod (a + b) m)
mul :: Integral a ⇒ Modulus s a → M s a → M s a → M s a
mul (Modulus m) (M a) (M b) = M (mod (a * b) m)
现在这个功能会起作用
testOK m a (b::w) = withModulus m
(\m → let a' = (M a :: ∀ sa. M sa w) ; b' = M b -- free indexes introduced
in unM $ add m (mul m a' a') (mul m b' b'))
然而,如果某个类型变量必须将其范围转义为统一,则它将失败
testKO m (M -> a) -- sa introduced
(b') = withModulus m
(\(m :: Modulus sm w) -- sm introduced
→ let b = M b' in unM $ add m (mul m a a) (mul m b b))
(统一sa == sm,sm
必须逃避其范围)
• Couldn't match type ‘s0’ with ‘s’
because type variable ‘s’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context:
Modulus s w -> w
at /Users/nrolland/Sync/clones/haskGist80/.stack-work/intero/intero88093-Bi.hs:(37,17)-(39,72)
Expected type: M s w
Actual type: M s0 w
错误消息使用定义中的名称s
报告此错误,而不是提供的名称sm
。这可能是次要的,但我想在更复杂的环境中难以阅读。
有没有办法强制使用名称?
完整代码:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UnicodeSyntax #-}
module Configuration where
--http://okmij.org/ftp/Haskell/tr-15-04.pdf
newtype Modulus s a = Modulus a deriving (Eq, Show)
newtype M s a = M a deriving (Eq, Show)
add :: Integral a ⇒ Modulus s a → M s a → M s a → M s a
add (Modulus m) (M a) (M b) = M (mod (a + b) m)
mul :: Integral a ⇒ Modulus s a → M s a → M s a → M s a
mul (Modulus m) (M a) (M b) = M (mod (a * b) m)
unM (M a) = a
data AnyModulus a = ∀ s. AnyModulus (Modulus s a)
makeModulus :: a → AnyModulus a
makeModulus a = AnyModulus (Modulus a)
withModulus ∷ a → (∀ s. Modulus s a → w ) → w
withModulus a k = k (Modulus a)
Integral w => w -> w -> w -> w
testOK m a (b::w) = withModulus m
(\m → let a' = (M a :: ∀ sa. M sa w) ; b' = M b -- free indexes introduced
in unM $ add m (mul m a' a') (mul m b' b'))
Integral w => w -> w -> w -> w
testKO m (M -> a) -- sa introduced
(b') = withModulus m
(\(m :: Modulus sm w) -- sm introduced
→ let b = M b' in unM $ add m (mul m a a) (mul m b b))
答案 0 :(得分:1)
也许这接近你所寻找的。 p>
testKO :: forall w. Integral w => w -> w -> w -> w
testKO m a' b' = let
a :: forall s. M s w
a = M a'
in withModulus m (\ m' → let
b = M b'
in unM $ add m' (mul m' a a) (mul m' b b))
问题是:
a
除非我们明确要求,否则不会获得多种类型a
才能使用多种类型,或withModulus
无法选择s
进行链接(M -> a)
这样的查看模式不允许AFAICS指定类型注释