我有大量类型的向量函数
f :: (M.MVector v r, PrimMonad m) =>
v (PrimState m) r -> v (PrimState m) r -> m ()
这些函数大多在原地工作,因此将它们的参数设置为可变向量很方便,以便我可以组合、迭代等。但是,在顶层,我只想使用不可变的“Haskell”/纯向量.
这是问题的一个例子:
{-# 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
编写的代码导致第 1 行出现错误:
Could not deduce (m ~ ST s)
Expected type: ST s ()
Actual type: m ()
in the return type of g, LINE 1
注释掉第 1 行会导致第 2 行出现错误:
Ambiguous type variable `m0' in the constraint:
(PrimMonad m0) arising from a use of `applyFun'
我尝试了各种显式类型(使用 ScopedTypeVariables、显式 foralls 等),但还没有找到解决第一个错误的方法。对于 LINE 1 错误,似乎m
应该简单地推断为,ST s
因为我在runST
.
对于第 2 行错误(第 1 行注释掉),我想出的唯一可行的方法是
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
这显然不能令人满意:我必须创建一个假类,使用更无意义的方法,其唯一工作是演示类参数的种类。然后我为所有内容创建一个通用实例,以便我可以m
在范围内topLevelFun
,以便我可以添加一个约束和强制转换f
。必须有更好的方法。
我可能在这里做错了各种各样的事情,所以任何建议都会有所帮助。