gpt4 book ai didi

haskell - 使用 monadic rank-2 类型

转载 作者:行者123 更新时间:2023-12-04 20:06:37 25 4
gpt4 key购买 nike

这是代码:

{-# 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))

这会导致错误:
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

但是,我不确定如何修复或诊断问题。它可能与位置良好(并且编写良好)的类型签名一样简单。

在试图弄清楚发生了什么时,我写了一个非 monadic 版本(对我没用),但它编译:
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 question 有关没有地方放字典的地方,但这真的只是在黑暗中刺伤。

最佳答案

一种解决方案是移动 PrimMonad DimFun 内的约束数据类型。

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

其余代码按原样编译,删除 s来自 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

将类约束移动到数据类型中对您来说可能看起来很可怕,但实际上,无论如何您已经在那里有了类约束。 PrimStatePrimMonad 的关联类型族,所以为了生产或消费 v (PrimState s) r ,您需要 PrimMonad约束。

如果你想避免它,你将不得不改变某些东西的类型。要了解为什么您拥有的函数类型错误,请考虑以下内容(需要 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

应该清楚为什么 g fm类型错误: g期待什么地方 forall s . PrimMonad s =>m 里面,这不是 fm 的情况.您将必须编写一个类型的函数:
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'

关于haskell - 使用 monadic rank-2 类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24745286/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com