临时类型变量的范围 [英] Scoping for temporary type variables
问题描述
我有大量的矢量函数
f ::(M.MVector vr,PrimMonad m)=>
v(PrimState m)r - > v(PrimState m)r - > m()
这些函数大多在原地工作,所以将它们的参数设置为a这样我就可以编写,迭代等等。但是,在顶层,我只想使用不可变的Haskell/纯矢量。
这个问题的一个例子是:$ $ p $ $ $ $ $ $ $ b $ {$#$ {$#$ $ $ $ $ $ $ $ $ $ $ $ $ $ { - #LANGUAGE TypeFamilies,
ScopedTypeVariables,
MultiParamTypeClasses,
FlexibleInstances# - }
导入Data.Vector.Generic作为V隐藏(eq)
导入Data.Vector.Generic.Mutable作为M
导入Control.Monad.ST
import Control.Monad.Primitive
f ::(M.MVector vr,PrimMonad m)=>
v(PrimState m)r - > v(PrimState m)r - > m()
f vIn vOut = do val< - M.read vIn 0
M.write vOut 0 val
applyFunc ::(M.MVector vr,PrimMonad m, V.Vector v'r,v〜Mutable v')=>
(v(PrimState m)r - > v(PrimState m)r - > m()) - > v'r - > v'r
applyFunc gx = runST $ do
y< - V.thaw x
gyy - LINE 1
V.unsafeFreeze y
topLevelFun: :(V.Vector vr)=> r - > vr
topLevelFun a =
let x = V.在applyFunc fx中复制10 a
- LINE 2
写入的代码导致LINE 1出错:
无法推断出m〜ST s)
预期类型:ST s()
实际类型:m()
,返回类型g,LINE 1
注释LINE 1导致LINE 2出错:
在使用`applyFun'
$ b引起的约束:
(PrimMonad m0)中含糊不清的类型变量`m0'
$ b我尝试了各种显式类型(使用ScopedTypeVariables,显式合并等),但还没有找到解决第一个错误的方法。对于LINE 1错误,似乎应该简单地将
m
推断为ST s
,因为我处于runST
。
对于LINE 2错误(LINE 1注释掉了),我唯一想到的作品是
class Fake mv其中
kindSig :: ma - > v b c
实例假m v
topLevelFun :: forall m v v'r。 (V.Vector v'r,M.MVector v r,PrimMonad m,Fake m v,v〜Mutable v')=> r - > v'r
topLevelFun a =
let x = V. applyFunc(f :: Transform mvr)中的10 a
x - LINE 2
这显然不令人满意:我必须创建一个假类,使用更无意义的方法,其唯一工作是展示类参数的种类。然后我创建了一个通用实例,以便我可以在
topLevelFun
范围内拥有m
,这样我就可以添加一个约束并铸造f
。 GOT是一种更好的方式。
我可能会在这里做很多错误的事情,所以任何建议都会有帮助。
解决方案以下类型的
applyFunc
是否适合您?applyFunc ::(Vector va)=>
(forall s。Mutable v s a - > Mutable v s a - > ST s())
- > v a - > va
只要您有
Rank2Types
扩展名,这是你需要的,因为你需要使用一个必须在所有 ST单元上工作的函数。原因是runST
的类型是(所有s ST s a) - >一个
,所以runST
之后的代码的主体需要为所有的s
工作,因此g
需要适用于所有s
。
(你可以改用一个可以与所有
PrimMonads
一起工作的函数,但是这些函数的数量会少得多)。
GHC无法推断更高的排名类型。有很好的理由不推断
RankNTypes
(它是不可判定的),尽管Rank2
在理论上是可推断的, GHC的人决定这个规则只要原则类型是Hindley-Milner类型就可以推断出来,这对于像我这样的人来说很容易推理,并且让编译器编写者的工作不那么难。
在关于获取元组的评论中。具有多态类型的元组需要
ImpredicativeTypes
并且可以像
applyFuncInt: :(Vector va)=>
((forall s。Mutable v s a - > Mutable v s a - > ST s()),Int)
- > v a - > va
applyFuncInt(g,_)x = runST $ do
y< - V.thaw x
gyy
V.unsafeFreeze y
虽然通常最好将数字作为单独的参数传递。
I have a large number of in place vector functions of the type
f :: (M.MVector v r, PrimMonad m) => v (PrimState m) r -> v (PrimState m) r -> m ()
These functions mostly work in-place, so it is convenient to have their argument be a mutable vector so that I can compose, iterate, etc. However, at the top level, I only want to work with immutable "Haskell"/pure vectors.
Here is an example of the problem:
{-# LANGUAGE TypeFamilies, ScopedTypeVariables, MultiParamTypeClasses, FlexibleInstances #-} import Data.Vector.Generic as V hiding (eq) import Data.Vector.Generic.Mutable as M import Control.Monad.ST import Control.Monad.Primitive f :: (M.MVector v r, PrimMonad m) => v (PrimState m) r -> v (PrimState m) r -> m () f vIn vOut = do val <- M.read vIn 0 M.write vOut 0 val applyFunc :: (M.MVector v r, PrimMonad m, V.Vector v' r, v ~ Mutable v') => (v (PrimState m) r -> v (PrimState m) r -> m ()) -> v' r -> v' r applyFunc g x = runST $ do y <- V.thaw x g y y -- LINE 1 V.unsafeFreeze y topLevelFun :: (V.Vector v r) => r -> v r topLevelFun a = let x = V.replicate 10 a in applyFunc f x -- LINE 2
The code as written results in an error on LINE 1:
Could not deduce (m ~ ST s) Expected type: ST s () Actual type: m () in the return type of g, LINE 1
Commenting out LINE 1 results in the error on LINE 2:
Ambiguous type variable `m0' in the constraint: (PrimMonad m0) arising from a use of `applyFun'
I've tried a variety of explicit typing (using ScopedTypeVariables, explicit foralls, etc) but haven't found a way to fix the first error. For the LINE 1 error, it seems that
m
should simply be inferred to beST s
since I'm in arunST
.For the LINE 2 error (with LINE 1 commented out), the only thing I've come up with that works is
class Fake m v where kindSig :: m a -> v b c instance Fake m v topLevelFun :: forall m v v' r . (V.Vector v' r, M.MVector v r, PrimMonad m, Fake m v, v ~ Mutable v') => r -> v' r topLevelFun a = let x = V.replicate 10 a in applyFunc (f::Transform m v r) x -- LINE 2
which is obviously unsatisfactory: I have to create a fake class, with an even more pointless method whose only job is to demonstrate the kinds of the class arguments. Then I create a generic instance for everything so that I can have
m
in scope intopLevelFun
, so that I can add a constraint and castf
. There has GOT to be a better way.I could be doing a wide variety of things wrong here, so any suggestions would be helpful.
解决方案Does the following type for
applyFunc
work for you?applyFunc :: (Vector v a) => (forall s. Mutable v s a -> Mutable v s a -> ST s ()) -> v a -> v a
That should compile with out problem so long as you have the
Rank2Types
extension, which you need because you work with a function that has to work on all ST monads. The reason for this is the type ofrunST
is(forall s. ST s a) -> a
, so the body of the code afterrunST
needs to work for alls
, henceg
needs to work for alls
.(You could instead take a function that work with all
PrimMonads
but there are strictly fewer of those).GHC can not infer higher rank types. There are very good reasons to not infer
RankNTypes
(it is undecidable), and althoughRank2
is in theory inferable, the GHC people decided for the rule "infer if and only if the principle type is a Hindley-Milner type" which for people like me is very easy to reason about, and makes the compiler writers job not so hard.In the comments you ask about taking a tuple. Tuples with polymorphic types require
ImpredicativeTypes
and can be done likeapplyFuncInt :: (Vector v a) => ((forall s. Mutable v s a -> Mutable v s a -> ST s ()),Int) -> v a -> v a applyFuncInt (g,_) x = runST $ do y <- V.thaw x g y y V.unsafeFreeze y
although, usually it would be better to simply pass the number as a separate argument.
这篇关于临时类型变量的范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文