簡體   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