简体   繁体   English

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

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

Here is my code: 这是我的代码:

...

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

and here is the error message that I get: 这是我得到的错误消息:

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 () }

How do I fix this? 我该如何解决?

One way to fix it is to bring the type variables s and g into scope using the ScopedTypeVariables extension, the other is to simply omit the local type signature on swap_op . 修复它的一种方法是使用ScopedTypeVariables扩展将类型变量sg放入范围,另一种方法是简单地省略swap_op上的本地类型签名。

If the local signature is omitted, the type can be inferred -- that leaves, however, the problem of the constraint 如果省略了局部签名,则可以推断出类型 - 但是,这会留下约束的问题

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

that is needed. 这是必要的。 There are two options, 有两种选择,

  • change the array type to STArray 将数组类型更改为STArray
  • use STUArray s indeed 确实使用STUArray

If you change the array type to STArray , no constraint is needed (since there is an instance MArray (STArray s) e (ST s) that covers all element types), and without the local type signature it compiles without problems. 如果将数组类型更改为STArray ,则不需要约束(因为存在覆盖所有元素类型的instance MArray (STArray s) e (ST s) ),并且没有本地类型签名,它编译时没有问题。

If you want to keep the STUArray s, the function can only be used where an instance is in scope. 如果要保留STUArray ,则只能在实例在范围内的情况下使用该函数。 It is best, usually, to provide such instances either where the class is defined (not an option here) or where the type is defined (that would be this module). 通常,最好在定义类的地方(这里不是选项)或定义类型的地方(将是此模块)提供此类实例。

So then you should write an 那么你应该写一个

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

in that module, with that instance, the constraint would be fulfilled and need not be placed on the function. 在该模块中,使用该实例,约束将被实现,并且不需要放在该函数上。 Note, however, that writing such an instance is not trivial. 但请注意,编写这样的实例并非易事。

Alternatively, you could add the constraint to the signature and load off the burden of defining an (orphan) instance to the user of swapLink . 或者,您可以将约束添加到签名中,并减轻为swapLink用户定义(孤立)实例的swapLink

I don't know what a NodeName is, but whether GraphEdgeYaml is an unboxable type seems doubtful. 我不知道NodeName是什么,但是GraphEdgeYaml是否是一个无法打包的类型似乎令人怀疑。 I would therefore recommend switching to STArray s. 因此我建议切换到STArray

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

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