Correspondência de padrões no tipo rank 2
Estou tentando entender por que uma versão desse código é compilada e outra não.
{-# LANGUAGE RankNTypes, FlexibleContexts #-}
module Foo where
import Data.Vector.Generic.Mutable as M
import Data.Vector.Generic as V
import Control.Monad.ST
import Control.Monad.Primitive
data DimFun v m r =
DimFun {dim::Int, func :: v (PrimState m) r -> m ()}
runFun1 :: (Vector v r, MVector (Mutable v) r) =>
(forall m . (PrimMonad m) => DimFun (Mutable v) m r) -> v r -> v r
runFun1 (DimFun dim t) x | V.length x == dim = runST $ do
y <- thaw x
t y
unsafeFreeze y
runFun2 :: (Vector v r, MVector (Mutable v) r) =>
(forall m . (PrimMonad m) => DimFun (Mutable v) m r) -> v r -> v r
runFun2 t x = runST $ do
y <- thaw x
evalFun t y
unsafeFreeze y
evalFun :: (PrimMonad m, MVector v r) => DimFun v m r -> v (PrimState m) r -> m ()
evalFun (DimFun dim f) y | dim == M.length y = f y
runFun2
compila bem (GHC-7.8.2), masrunFun1
resulta em erros:
Could not deduce (PrimMonad m0) arising from a pattern
from the context (Vector v r, MVector (Mutable v) r)
bound by the type signature for
tfb :: (Vector v r, MVector (Mutable v) r) =>
(forall (m :: * -> *). PrimMonad m => TensorFunc m r) -> v r -> v r
at Testing/Foo.hs:(26,8)-(28,15)
The type variable ‘m0’ is ambiguous
Note: there are several potential instances:
instance PrimMonad IO -- Defined in ‘Control.Monad.Primitive’
instance PrimMonad (ST s) -- Defined in ‘Control.Monad.Primitive’
In the pattern: TensorFunc _ f
In an equation for ‘tfb’:
tfb (TensorFunc _ f) x
= runST
$ do { y <- thaw x;
f y;
unsafeFreeze y }
Couldn't match type ‘m0’ with ‘ST s’
because type variable ‘s’ would escape its scope
This (rigid, skolem) type variable is bound by
a type expected by the context: ST s (v r)
at Testing/Foo.hs:(29,26)-(32,18)
Expected type: ST s ()
Actual type: m0 ()
Relevant bindings include
y :: Mutable v s r (bound at Testing/Foo.hs:30:3)
f :: forall (v :: * -> * -> *).
MVector v r =>
v (PrimState m0) r -> m0 ()
(bound at Testing/Foo.hs:29:19)
In a stmt of a 'do' block: f y
In the second argument of ‘($)’, namely
‘do { y <- thaw x;
f y;
unsafeFreeze y }’
Could not deduce (s ~ PrimState m0)
from the context (Vector v r, MVector (Mutable v) r)
bound by the type signature for
tfb :: (Vector v r, MVector (Mutable v) r) =>
(forall (m :: * -> *). PrimMonad m => TensorFunc m r) -> v r -> v r
at Testing/Foo.hs:(26,8)-(28,15)
‘s’ is a rigid type variable bound by
a type expected by the context: ST s (v r) at Testing/Foo.hs:29:26
Expected type: Mutable v (PrimState m0) r
Actual type: Mutable v s r
Relevant bindings include
y :: Mutable v s r (bound at Testing/Foo.hs:30:3)
f :: forall (v :: * -> * -> *).
MVector v r =>
v (PrimState m0) r -> m0 ()
(bound at Testing/Foo.hs:29:19)
In the first argument of ‘f’, namely ‘y’
In a stmt of a 'do' block: f y
Tenho certeza de que o tipo rank-2 é o culpado, possivelmente causado por uma restrição de monomorfismo. No entanto, como sugerido em umpergunta anterior meu, eu habilitei-XNoMonomorphismRestriction
, mas obteve o mesmo erro.
Qual é a diferença entre esses trechos de código aparentemente idênticos?