是否存在类似于可变数组的MArray类的引用的类型类?

dfe*_*uer 4 haskell mutable typeclass

MArray类提供了通用函数,用于在ST和IO上下文中处理各种类型的可变数组.我无法找到一个类似的类来处理STRefs和IORefs.这样的事情存在吗?

GS *_*ica 6

ref-fd包提供:

class Monad m => MonadRef r m | m -> r where
    [...]
Run Code Online (Sandbox Code Playgroud)

或与类型系列,ref-tf:

class Monad m => MonadRef m where
    type Ref m :: * -> *
    [...]
Run Code Online (Sandbox Code Playgroud)

另一个答案表明monad-statevar包没有功能依赖.它还具有独立HasGetHasPut成员,在没有抽象newRef功能.

除了每种方法中的不同方法之外,功能依赖性是设计权衡.考虑以下两个简化类:

class MRef1 r m where
   newRef1 :: a -> m (r a)
   readRef1 :: r a -> m a

class MRef2 r m | m -> r where
   newRef2 :: a -> m (r a)
   readRef2 :: r a -> m a
Run Code Online (Sandbox Code Playgroud)

使用时MRef1,monad类型和引用类型都可以自由变化,因此以下代码具有类型错误:

useMRef1 :: ST s Int
useMRef1 = do
   r <- newRef1 5
   readRef1 r

No instance for (MRef1 r0 (ST s)) arising from a use of `newRef1'
The type variable `r0' is ambiguous
Run Code Online (Sandbox Code Playgroud)

我们必须在某个地方添加一个额外的类型签名来表示我们想要使用STRef.

相比之下,相同的代码适用于MRef2没有任何额外签名.定义上的签名表示整个代码具有类型ST s Int,结合功能依赖性m -> r意味着r给定m类型只有一种类型,因此编译器知道我们现有的实例是唯一可能的实例,我们必须要使用STRef.

另一方面,假设我们想要创建一种新的引用,例如STRefHistory跟踪所有已存储在其中的值:

newtype STRefHistory s a = STRefHistory (STRef s [a])
Run Code Online (Sandbox Code Playgroud)

MRef1,因为我们被允许多个引用类型相同的单子类型的实例是罚款:

instance MRef1 (STRefHistory s) (ST s) where
   newRef1 a = STRefHistory <$> newSTRef [a]
   readRef1 (STRefHistory r) = head <$> readSTRef r
Run Code Online (Sandbox Code Playgroud)

但是等效的MRef2实例失败了:

Functional dependencies conflict between instance declarations:
  instance MRef2 (STRef s) (ST s) -- Defined at mref.hs:28:10
  instance MRef2 (STRefHistory s) (ST s) -- Defined at mref.hs:43:10
Run Code Online (Sandbox Code Playgroud)

我还提到了类型族版本,它在功能依赖性方面表现力非常相似; 引用类型是monad类型的"类型函数",因此每个monad只能有一个.语法最终有点不同,特别是你可以MonadRef m在约束中说,而不说明约束中的引用类型.

具有相反的功能依赖性也是合理的:

class MRef2 r m | r -> m where
Run Code Online (Sandbox Code Playgroud)

这样每个引用类型只能存在一个monad中,但是你仍然可以为monad提供多种引用类型.那么你需要在引用上输入类型签名,而不是整体上的monadic计算.


r3m*_*m0t 5

Control.Monad.StateVar有一个类型类,它可以让您getputIORefs和STRefs相同.