Haskell 中随机数生成的参数化边界

问题描述 投票:0回答:1

我对 Haskell 还很陌生,我正在尝试创建一个函数来生成有限数字数组,同时考虑到一些开始和结束边界。如果我使用以下功能...

 finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => n -> g -> ([a], g)
 finiteRandoms 0 g = ([], g)
 finiteRandoms n g =
     let (value, newGen) = randomR (20,100) g
         (restOfList, finalGen) = finiteRandoms (n-1) newGen
     in  (value:restOfList, finalGen)

我运行以下命令...

finiteRandoms 3 (mkStdGen 3)

我用新的生成器获得了一个 Int 数组

([61,33,82],StdGen {unStdGen = SMGen 9186733390819170434 2092789425003139053})

我想做的是向标记起点和终点的函数添加两个新参数。在我分享的函数中,它代表数字 20 和 100 。像这样的东西

finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => n -> n -> n-> g -> ([a], g)
   finiteRandoms 0 start end g = ([], g)
   finiteRandoms n start end g =
         let (value, newGen) = randomR (start,end) g
             (restOfList, finalGen) = finiteRandoms (n-1) newGen
         in  (value:restOfList, finalGen)

但是当我通过 ghci 加载它时,出现以下错误

randomSample.hs:19:10: error: [GHC-83865]
    • Couldn't match expected type: n -> g0 -> ([a0], g0)
                  with actual type: (a1, b)
    • In the pattern: (restOfList, finalGen)
      In a pattern binding:
        (restOfList, finalGen) = finiteRandoms (n - 1) newGen
      In the expression:
        let
          (value, newGen) = randomR (start, end) g
          (restOfList, finalGen) = finiteRandoms (n - 1) newGen
        in (value : restOfList, finalGen)
    • Relevant bindings include
        value :: n (bound at randomSample.hs:18:11)
        end :: n (bound at randomSample.hs:17:24)
        start :: n (bound at randomSample.hs:17:18)
        n :: n (bound at randomSample.hs:17:16)
        finiteRandoms :: n -> n -> n -> g -> ([a], g)
          (bound at randomSample.hs:16:2)
   |
19 |          (restOfList, finalGen) = finiteRandoms (n-1) newGen
   |          ^^^^^^^^^^^^^^^^^^^^^^

randomSample.hs:20:11: error: [GHC-25897]
    • Couldn't match expected type ‘a’ with actual type ‘n’
      ‘n’ is a rigid type variable bound by
        the type signature for:
          finiteRandoms :: forall n g a.
                           (Eq n, Num n, RandomGen g, Random a, Num a) =>
                           n -> n -> n -> g -> ([a], g)
        at randomSample.hs:15:2-92
      ‘a’ is a rigid type variable bound by
        the type signature for:
          finiteRandoms :: forall n g a.
                           (Eq n, Num n, RandomGen g, Random a, Num a) =>
                           n -> n -> n -> g -> ([a], g)
        at randomSample.hs:15:2-92
    • In the first argument of ‘(:)’, namely ‘value’
      In the expression: value : restOfList
      In the expression: (value : restOfList, finalGen)
    • Relevant bindings include
        value :: n (bound at randomSample.hs:18:11)
        end :: n (bound at randomSample.hs:17:24)
        start :: n (bound at randomSample.hs:17:18)
        n :: n (bound at randomSample.hs:17:16)
        finiteRandoms :: n -> n -> n -> g -> ([a], g)
          (bound at randomSample.hs:16:2)
   |
20 |      in  (value:restOfList, finalGen)
   |           ^^^^^
Failed, no modules loaded.

如何参数化这两个边界(开始/结束)?谢谢。

haskell random
1个回答
0
投票

您忘记在递归调用中添加

start
end
start
end
也需要是
g

类型
finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => n -> a -> a -> g -> ([a], g)
finiteRandoms 0 start end g = ([], g)
finiteRandoms n start end g =
     let (value, newGen) = randomR (start,end) g
         (restOfList, finalGen) = finiteRandoms (n-1) start end newGen
     in  (value:restOfList, finalGen)

但很可能,最好在这里使用辅助函数:

finiteRandoms :: (Eq n, Num n, RandomGen g, Random a, Num a) => a -> a -> n -> g -> ([a], g)
finiteRandoms start end = go
   where go 0 g = ([], g)
         go n g =
             let (value, newGen) = randomR (start,end) g
                 (restOfList, finalGen) = go (n-1) newGen
             in  (value:restOfList, finalGen)
© www.soinside.com 2019 - 2024. All rights reserved.