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

これを修正する 1 つの方法は、型変数sを拡張機能gを使用してスコープに入れることです。もう 1 つScopedTypeVariablesは、単純に のローカル型シグネチャを省略することswap_opです。

ローカル署名が省略されている場合、型は推測できますが、制約の問題は残ります。

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

それが必要です。2 つのオプションがあります。

  • 配列タイプをに変更しますSTArray
  • STUArray実際に sを使用する

配列型を に変更するとSTArray、(すべての要素型をカバーする があるため) 制約は必要instance MArray (STArray s) e (ST s)なく、ローカル型シグネチャがなくても問題なくコンパイルされます。

sを保持したい場合STUArray、関数はインスタンスがスコープ内にある場合にのみ使用できます。通常、そのようなインスタンスは、クラスが定義されている場所 (ここではオプションではありません) または型が定義されている場所 (このモジュールになります) に提供するのが最善です。

それで、あなたは書くべきです

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

そのモジュールでは、そのインスタンスで制約が満たされ、関数に配置する必要はありません。ただし、そのようなインスタンスを作成するのは簡単ではないことに注意してください。

または、署名に制約を追加して、(孤立した) インスタンスを定義する負担を のユーザーに負わせることもできますswapLink

a が何かはわかりませんが、unboxable 型NodeNameかどうかは疑わしいようです。GraphEdgeYamlしたがって、STArrays に切り替えることをお勧めします。

于 2012-12-06T11:24:18.320 に答える