1

这是我的代码:

...

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

我该如何解决?

4

1 回答 1

3

修复它的一种方法是使用扩展将类型变量带入范围s,另一种方法是简单地省略.gScopedTypeVariablesswap_op

如果省略了本地签名,则可以推断出类型——然而,这留下了约束的问题

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

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

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

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

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

那么你应该写一个

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

在该模块中,通过该实例,将满足约束并且无需将其置于函数上。但是请注意,编写这样的实例并非易事。

或者,您可以将约束添加到签名中,并减轻为swapLink.

我不知道 aNodeName是什么,但是否GraphEdgeYaml是不可装箱的类型似乎值得怀疑。因此,我建议切换到STArrays。

于 2012-12-06T11:24:18.320 回答