繁体   English   中英

无法将小型C#“Random String”函数转换为Haskell

[英]Trouble translating small C# “Random String” function to Haskell

我在我的公司代码库中看到了以下代码,并且自己想到“该死的linq是一个很好的路线,我想把它翻译成Haskell,看看它在实际的功能语言中是什么样的”

static Random random = new Random();
static string RandomString(int length)
{
    const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
    return new string(Enumerable.Repeat(chars, length)
                                .Select(s => s[random.Next(s.Length)])
                                .ToArray());
}

然而,由于在这种语言中生成随机数有多么尴尬,我在使用简洁直接的Haskell翻译方面遇到了一些麻烦。

我考虑了几种方法。 C#代码的最直接转换只生成一个随机索引,然后使用它代替random.Next(s.Length) 但我需要生成多个索引,而不是单个索引。

然后我考虑做一个IO Int随机数动作列表,但我无法弄清楚如何通过并将IO动作列表转换为实际的随机数。

因此,与C#相比,我最终编写的Haskell代码看起来相当复杂(在这种情况下我没有预料到),我甚至还没有让它工作。

我的问题是,C#对Haskell的自然翻译是什么? 或者更一般地说,如何在Haskell中生成指定长度的随机字符串(因为这种C#方式似乎不能很好地转换为Haskell)?

注意:我主要感兴趣的是在Haskell中生成随机字符串的算法。 我对任何为我工作的标准库都不感兴趣

对Haskell的自然转换涉及到某种IO (因为你需要随机性)。 由于您实际上是在尝试执行n次选择字符的操作,因此您希望使用replicateM 然后,为了获得范围内的随机数,您可以使用randomRIO

import Control.Monad (replicateM)
import System.Random (randomRIO)

randomString :: Int -> IO String
randomString n = replicateM n (do r <- randomRIO (0,m); pure (chars !! r))
  where
    chars = ['A'..'Z'] ++ ['0'..'9']
    m = length chars

由于您想要在特定范围内只有一串字符,因此这有点复杂。 否则,你有一个班轮: randomString n = replicateM n randomIO


也就是说,更忠实的翻译将使用conduit 我不打算包含导入和语言编译指示(因为它们有点痛苦)。 这看起来更像你在C#中编写的内容:

randomString' :: Int -> IO String
randomString' n = runConduit $ replicate n chars
                            .| mapM (\cs -> do r <- randomRIO (0,m); pure (cs !! r))
                            .| sinkList
  where
    chars = ['A'..'Z'] ++ ['0'..'9']
    m = length chars

暂无
暂无

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

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