I'm experimenting with a type-level permission system, and I'm trying to disallow assignment of values which do not originate from the same "source", i.e:
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
I've experimented with rank N (or impredicative?) types:
type Value = forall a. Value a ...
but both cases above unify. If I constrain a
:
type Value = forall a. Unique a => Value a ...
both cases don't. Is there a way to achieve something like that? Is it possible in Haskell?
(Note: the Value
constructor would not be public, i.e. there's no way to create a standalone Value
.)
As user2407038 mentionned, you could use phantom types to do what you want.
However, there is a workaround:
But you can prevent the user from writing
getBValue
if you hide theValue
constructor (by not exporting it). But that would mean that there is absolutely no way to extract the actual value out of aValue
. You could still instantiateValue
for theFunctor
,Applicative
andMonad
so that you can work with those wrapped values directly. But you would have to changeValue
to a more general form. Here is an example: