繁体   English   中英

如何正确限定使用(转换)ST和随机monad的类型

[英]How to correctly qualify types for working with the (transformed) ST and random monads

这是我的代码:

...

import System.Random ( RandomGen, next, split )
import qualified Data.Array.MArray as MAI
import Data.Array.ST.Safe( STUArray )
import Control.Monad.ST.Safe(ST)
import qualified Control.Monad.Random as CMR
import Control.Monad.Trans.Class( lift )

data GraphEdgeYaml = GraphEdgeYaml { 
    specie1:: NodeName,
    specie2 :: NodeName,
    sign :: Int,
    speed :: Int
}

type LinksSTA s = STUArray s Int GraphEdgeYaml

-- Change a simple link 
swapLink :: RandomGen g => 
    LinksSTA s
    -> g
    -> ST s g
swapLink graph generator = 
   let
      swap_op :: CMR.RandT g (ST s) ()
      swap_op = do 
          (low_limit, high_limit) <- lift $ MAI.getBounds graph
          idx_value <- CMR.getRandomR (low_limit, high_limit)
          return ()
   in do
      (_, new_generator) <- CMR.runRandT  swap_op generator
      return new_generator

这是我得到的错误消息:

hs/SignMatrixBuild/Randomize.hs:43:26:
    Could not deduce (RandomGen g1)
      arising from a use of `CMR.getRandomR'
    from the context (RandomGen g)
      bound by the type signature for
                 swapLink :: RandomGen g => LinksSTA s -> g -> ST s g
      at hs/SignMatrixBuild/Randomize.hs:(38,1)-(47,28)
    Possible fix:
      add (RandomGen g1) to the context of
        the type signature for swap_op :: CMR.RandT g1 (ST s1) ()
        or the type signature for
             swapLink :: RandomGen g => LinksSTA s -> g -> ST s g
    In a stmt of a 'do' block:
      idx_value <- CMR.getRandomR (low_limit, high_limit)
    In the expression:
      do { (low_limit, high_limit) <- lift $ MAI.getBounds graph;
           idx_value <- CMR.getRandomR (low_limit, high_limit);
           return () }
    In an equation for `swap_op':
        swap_op
          = do { (low_limit, high_limit) <- lift $ MAI.getBounds graph;
                 idx_value <- CMR.getRandomR (low_limit, high_limit);
                 return () }

我该如何解决?

修复它的一种方法是使用ScopedTypeVariables扩展将类型变量sg放入范围,另一种方法是简单地省略swap_op上的本地类型签名。

如果省略了局部签名,则可以推断出类型 - 但是,这会留下约束的问题

MAI.MArray (STUArray s) GraphEdgeYaml (ST s)

这是必要的。 有两种选择,

  • 将数组类型更改为STArray
  • 确实使用STUArray

如果将数组类型更改为STArray ,则不需要约束(因为存在覆盖所有元素类型的instance MArray (STArray s) e (ST s) ),并且没有本地类型签名,它编译时没有问题。

如果要保留STUArray ,则只能在实例在范围内的情况下使用该函数。 通常,最好在定义类的地方(这里不是选项)或定义类型的地方(将是此模块)提供此类实例。

那么你应该写一个

instance MAI.MArray (STUArray s) GraphEdgeYaml (ST s)

在该模块中,使用该实例,约束将被实现,并且不需要放在该函数上。 但请注意,编写这样的实例并非易事。

或者,您可以将约束添加到签名中,并减轻为swapLink用户定义(孤立)实例的swapLink

我不知道NodeName是什么,但是GraphEdgeYaml是否是一个无法打包的类型似乎令人怀疑。 因此我建议切换到STArray

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM