我正在尝试使用类型级别的权限系统,并且我试图禁止分配不是源自相同"来源"的值,即:
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
。)
答案 0 :(得分: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
。但这意味着绝对无法从Value
中提取实际值。您仍然可以为Value
,Functor
和Applicative
实例化Monad
,以便您可以直接使用这些包装的值。但您必须将Value
更改为更一般的形式。这是一个例子:
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