Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 使用一元秩-2类型_Haskell_Higher Rank Types - Fatal编程技术网

Haskell 使用一元秩-2类型

Haskell 使用一元秩-2类型,haskell,higher-rank-types,Haskell,Higher Rank Types,代码如下: {-# 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 DimF

代码如下:

{-# 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))
但是,我不确定如何修复或诊断该问题。它可能像一个好地方(而且写得很好)的类型签名一样简单

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

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)

这让我觉得上面的错误与字典没有地方可去的地方有关,但这真的只是一个暗中的尝试

一种解决方案是将
PrimMonad
约束移动到
DimFun
数据类型中

data DimFun v r = DimFun 
   { dim  :: Int
   , func :: forall s . PrimMonad s => v (PrimState s) r -> s ()
   }
其余代码按原样编译,从
DimFun
中删除
s
参数:

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
将类约束移动到数据类型中可能会让您感到害怕,但实际上,您已经有了类约束
PrimState
PrimMonad
的关联类型族,因此为了生成或使用
v(PrimState s)r
,需要
PrimMonad
约束

然而,如果你想避免它,你必须改变某些东西的类型。要了解为什么您的函数是非类型化的,请考虑下面的(这需要<代码> iVixTiVePype < /代码>):

应该弄清楚为什么
g fm
类型错误:
g
期望所有
类型错误的内容。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'

看起来你可能做了一个双重职位。这可能应该被删除,答案在这里:@jberryman这两个问题中的问题是否相关对我来说并不明显(尽管代码的某些子集实际上是相同的)。这就是为什么我发布了两个问题。这可能是一个不明确的多态性问题。你可以用一个容器包装你的通用量化字体。@J.Abrahamson我宁愿有更多的注释也不要用包装器。注释会去哪里?它们看起来会是什么样子?@Eric一旦你看到需要多少注释才能使其工作,你可能会改变主意。这两种解决方案都很好。我只希望这是我需要做的事情,这一点更加明显!这也解决了问题,因为我不再需要对排名2的类型进行模式匹配。我唯一能要求的是一个提示,告诉我如何知道这是未来应该做的正确的事情。为什么我更喜欢数据中的rank-2类型而不是数据中的rank-2类型?在我看来,您应该总是在数据类型中选择通用的量化字段,而不是不可预测的类型。对于不可预测类型,几乎总是很难判断正确的类型应该是什么,正如您所看到的,正确类型和错误类型之间的差异通常非常小。更重要的是,typechecker对您毫无用处,因为它无法推断不精确的类型,而您遇到的类型错误将是可怕的。
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 
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'