2

我正在尝试使用类型级别的权限系统,并且我试图禁止分配不来自同一“来源”的值,即:

data A = A { a :: Value, b :: Value }

modify :: A -> A
modify (A v) = A $ v { a = v.a } -- should work
modify (A v) = A $ v { a = v.b } -- should *NOT* work

我已经尝试过 N 级(或暗示性?)类型:

type Value = forall a. Value a ...

但以上两种情况统一。如果我限制a

type Value = forall a. Unique a => Value a ...

两种情况都没有。有没有办法实现这样的目标?在 Haskell 中可以吗?

(注意:Value构造函数不会是公开的,即无法创建独立的Value.)

4

1 回答 1

4

正如 user2407038 提到的,您可以使用幻像类型来做您想做的事。

{-# LANGUAGE DataKinds, GADTs, KindSignatures #-}

data ValueType = A | B

data Value :: ValueType -> * where
    Value :: Int → Value t

data V = V { a :: Value A, b :: Value B }

modify ∷ V -> V
modify v = v { a = a v }  -- no error
modify v = v { a = b v }  -- Couldn't match type ‘'B’ with ‘'A’

但是,有一个解决方法:

modify ∷ V -> V
modify v = v { a = Value $ getBValue (b v) }
    where getBValue (Value x) = x

getBValue但是,如果您隐藏Value构造函数(通过不导出它),您可以阻止用户写入。但这意味着绝对没有办法从 a 中提取实际值Value。您仍然可以为 , 实例化Value,以便Functor您可以直接使用这些包装的值。但是您必须更改为更通用的形式。这是一个例子:ApplicativeMonadValue

data Value :: ValueType -> * -> * where
    Value :: a -> Value t a

instance Functor (Value t) where
    fmap f (Value x) = Value (f x)

instance Applicative (Value t) where
    pure = Value
    Value f <*> Value x = Value (f x)

instance Monad (Value t) where
    Value x >>= f = f x
于 2017-06-18T15:10:24.917 回答