使用monadic rank-2类型 [英] Using a monadic rank-2 type

查看:123
本文介绍了使用monadic rank-2类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下是代码:

  { - #LANGUAGE RankNTypes,FlexibleContexts,ScopedTypeVariables# - } 

模块Foo其中

导入Data.Vector.Generic.Mutable为M
导入Data.Vector.Generic作为V
导入Control.Monad.ST
导入控件.Monad.Primitive
import Control.Monad

data DimFun vsr =
DimFun {dim :: Int,func :: v(PrimState s)r - > s()}

runFun ::(Vector v r)=>
(全部s(PrimMonad s)=> DimFun(Mutable v)s r) - > v r - > vr
runFun tx = runST $ do
y< - thaw x
evalFun ty
unsafeFreeze y

evalFun ::(PrimMonad s,MVector vr) => DimFun v s r - > v(PrimState s)r - > s()
evalFun(DimFun dim f)y | dim == M.length y = f y

fm ::(MVector v r,PrimMonad s,Num r,Monad m)=> m(DimFun v s r)
fm =错误

f :: forall v r m。 (Vector v r,Num r,Monad m)=> m(vr - > vr)
f = liftM runFun $(fm :: forall s。(PrimMonad s)=> m(DimFun(Mutable v)sr))



$ b

这导致错误:

  Couldn' t匹配类型'DimFun(Mutable v)s0 r'
with'forall(s :: * - > *)。 PrimMonad s => DimFun(Mutable v)s r'
预期类型:DimFun(Mutable v)s0 r - > v r - > v r
实际类型:(forall(s :: * - > *)。
PrimMonad s =>
DimFun(Mutable v)s r)
- > v r - > vr
相关绑定包括
f :: m(vr - > vr)(绑定在Testing / Foo.hs:36:1)
在'liftM'的第一个参数中, runFun'
在表达式中:liftM runFun

然而,我不确定如何修复或诊断问题。它可能就像写得很好(写得很好)的类型签名一样简单。



在试图弄清楚发生了什么的时候,我写了一个非单调版本(对我无用),但它编译:

  gm ::(MVector vr,PrimMonad s,Num r)=> ; DimFun v s r 
gm =错误

g :: forall v r m。 (Vector v r,Num r)=> v r - > vr
g = runFun(gm :: forall s。(PrimMonad s)=> DimFun(Mutable v)sr)

这使得我上面的错误与这个问题有关字典无处可去,但这实际上只是一个黑暗中的刺。解决方案一个解决方案是将 PrimMonad 约束移动到 DimFun 数据类型。

  data DimFun v r = DimFun 
{dim :: Int $ b $,func :: forall s。 PrimMonad s => v(PrimState s)r - > s()
}

其余代码按原样编译, code $ s code $ s code $> c $ c> runFun :: Vector vr => DimFun(Mutable v)r - > v r - > v r
runFun = ...

evalFun ::(PrimMonad s,MVector v r)=> DimFun v r - > v(PrimState s)r - > s()
evalFun = ...

fm ::(MVector v r,Num r,Monad m)=> m(DimFun v r)
fm = ...

f ::(Vector v r,Num r,Monad m)=> m(vr - > vr)
f = liftM runFun fm

数据类型对你来说可能看起来很可怕,但实际上,你已经有类限制了。 PrimState PrimMonad 的关联类型族,因此为了生成或使用 v (PrimState s)r ,您需要 PrimMonad 约束。

如果你想避免它,你将不得不改变某种东西。要明白为什么你的函数有问题,请考虑以下内容(它需要 ImpredictiveTypes ):

  fm ::(MVector vr,PrimMonad s,Num r,Monad m)=> m(DimFun v s r)
fm =错误

g ::(Vector v r,Monad m)
=> m(forall s。PrimMonad s => DimFun(Mutable v)s r) - > m(vr - > vr)
g = liftM runFun

应该清除为什么 g fm 不符合格式: g 需要全部内容。 PrimMonad s => 里面 m ,这不是 fm 。你必须写一个类型的函数:

  fm'::(MVector vr,Monad m,Num r)=> ; m(forall s。PrimMonad s => DimFun v s r)
fm'= error

f :: forall v r m。 (Vector v r,Num r,Monad m)=> m(v r - > v r)
f = g fm'


Here's the code:

{-# LANGUAGE RankNTypes, FlexibleContexts, ScopedTypeVariables #-}

module Foo where

import Data.Vector.Generic.Mutable as M
import Data.Vector.Generic as V
import Control.Monad.ST
import Control.Monad.Primitive
import Control.Monad

data DimFun v s r = 
  DimFun {dim::Int, func :: v (PrimState s) r -> s ()}

runFun :: (Vector v r) => 
  (forall s . (PrimMonad s) => DimFun (Mutable v) s r) -> v r -> v r
runFun t x = runST $ do
  y <- thaw x
  evalFun t y
  unsafeFreeze y

evalFun :: (PrimMonad s, MVector v r) => DimFun v s r -> v (PrimState s) r -> s ()
evalFun (DimFun dim f) y | dim == M.length y = f y

fm :: (MVector v r, PrimMonad s, Num r, Monad m) => m (DimFun v s r)
fm = error ""

f :: forall v r m . (Vector v r, Num r, Monad m) => m (v r -> v r)
f = liftM runFun $ (fm :: forall s . (PrimMonad s) => m (DimFun (Mutable v) s r))

This results in errors:

Couldn't match type ‘DimFun (Mutable v) s0 r’
              with ‘forall (s :: * -> *). PrimMonad s => DimFun (Mutable v) s r’
Expected type: DimFun (Mutable v) s0 r -> v r -> v r
  Actual type: (forall (s :: * -> *).
                PrimMonad s =>
                DimFun (Mutable v) s r)
               -> v r -> v r
Relevant bindings include
  f :: m (v r -> v r) (bound at Testing/Foo.hs:36:1)
In the first argument of ‘liftM’, namely ‘runFun’
In the expression: liftM runFun

However, I'm not sure how to fix or diagnose the problem. It might be as simple as a well-place (and well-written) type signature.

While trying to figure out what was going on, I write a non-monadic version (useless to me), but it compiles:

gm :: (MVector v r, PrimMonad s, Num r) => DimFun v s r
gm = error ""

g :: forall v r m . (Vector v r, Num r) => v r -> v r
g = runFun (gm :: forall s . (PrimMonad s) => DimFun (Mutable v) s r)

This makes me thing the error above is related to the this question where there is no place for the dictionary to go, but that's really just a stab in the dark.

解决方案

One solution is to move the PrimMonad constraint inside the DimFun datatype.

data DimFun v r = DimFun 
   { dim  :: Int
   , func :: forall s . PrimMonad s => v (PrimState s) r -> s ()
   }

The rest of your code compiles as-is, removing the s parameter from DimFun:

runFun :: Vector v r => DimFun (Mutable v) r -> v r -> v r
runFun = ...

evalFun :: (PrimMonad s, MVector v r) => DimFun v r -> v (PrimState s) r -> s () 
evalFun = ...

fm :: (MVector v r, Num r, Monad m) => m (DimFun v r)
fm = ...

f :: (Vector v r, Num r, Monad m) => m (v r -> v r)
f = liftM runFun fm

Moving the class constraint into the datatype may seem scary to you, but in reality, you already had the class constraint there anyways. PrimState is an associated type family of PrimMonad, so in order to produce or consume a v (PrimState s) r, you need the PrimMonad constraint.

If you want to avoid it nevertheless, you will have to change the type of something. To see why the function you have is illtyped, consider the following (which requires ImpredictiveTypes):

fm :: (MVector v r, PrimMonad s, Num r, Monad m) => m (DimFun v s r)
fm = error ""

g :: (Vector v r, Monad m) 
  => m (forall s . PrimMonad s => DimFun (Mutable v) s r) -> m (v r -> v r)
g = liftM runFun 

It should be cleared why g fm is illtyped: g expects something where the forall s . PrimMonad s => is inside the m, which is not the case for fm. You will have to write a function of type:

fm' :: (MVector v r, Monad m, Num r) => m (forall s . PrimMonad s => DimFun v s r)
fm' = error ""

f :: forall v r m . (Vector v r, Num r, Monad m) => m (v r -> v r)
f = g fm'

这篇关于使用monadic rank-2类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆