Weird types when masking read,write,alloc effects
anfelor opened this issue · comments
For mask<read>
, Koka infers the following type signature:
fun mask-read(f : () -> <alloc<h>,write<h>|e> a) : e a
mask<read>{ f() }
I am quite surprised by that and would have expected the type signature:
fun mask-read(f : () -> e ()) : <read<h>|e> ()
mask<read>{ f() }
However, Koka can not compile this:
Type.InferMonad.runUnify: should never fail!: NoMatch
CallStack (from HasCallStack):
error, called at src/Common/Failure.hs:46:12 in koka-3.1.1-GrUKw6cowJ9E7PPCKFMvzQ:Common.Failure
raise, called at src/Common/Failure.hs:32:5 in koka-3.1.1-GrUKw6cowJ9E7PPCKFMvzQ:Common.Failure
failure, called at src/Type/InferMonad.hs:653:17 in koka-3.1.1-GrUKw6cowJ9E7PPCKFMvzQ:Type.InferMonad
Koka accepts the definition:
fun mask-write(f)
mask<write>{ f() }
and tells me that the type is fun mask-write : forall<a,h,e> (f : () -> <alloc<h>,read<h>|e> a) -> e a
. However, Koka does not accept the definition with this signature:
fun mask-write(f : () -> <alloc<h>,read<h>|e> a) : e a
mask<write>{ f() }
and fails with:
effects do not match
context : fun mask-write(f : () -> <alloc<h>,read<h>|e> a) : e a
mask<write>{ f() }
term :
mask<write>{ f() }
inferred effect: <write<_h>,alloc<$h1>,read<$h1>|$e>
expected effect: $e
In contrast to those cases, Koka does the right thing for alloc
:
fun mask-alloc(f : () -> e a) : <alloc<h>|e> a
mask<alloc>{ f() }
For completeness, these are the signatures of composing the masks:
fun mask-read-write(f : () -> <alloc<h>|e> a) : e a
mask<read>{ mask<write>{ f() }}
fun mask-read-alloc(f : () -> <write<h>|e> a) : e a
mask<read>{ mask<alloc>{ f() }}
// This definition gives a type error for wrong signature,
// but infers exactly this signature when none is given
// (like for the plain mask<write> above):
fun mask-write-alloc(f : () -> <read<h>|e> a) : e a
mask<write>{ mask<alloc>{ f() }}
fun mask-read-write-alloc(f : () -> e ()) : e ()
mask<read>{ mask<write>{ mask<alloc>{ f() }}}
Notice in particular that masking all these effects in the identity. In particular, this prevents us from writing a custom version of the mask<st>
operator requested in #155. I could imagine that this is caused by implicitly trying to apply the run
operation?