在haskell中强制类型变量名

时间:2017-07-19 10:20:06

标签: haskell

假设我有幻影类型

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)

对于ModulusM

类型,加上一些原型,属于同一类型索引
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))

1 个答案:

答案 0 :(得分:1)

也许这接近你所寻找的。

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指定类型注释