我对Haskell和硬FP很新。我一直试图想出一个能为我的项目生成特殊类型ID的函数。该ID有4组8位数字。前两组始终为零,另外两组为随机8位十六进制数。这是我提出的代码,但似乎要调用很多东西来实现简单的结果。做这样的事情的Haskell方式是什么?
import Data.List (intercalate)
import System.Random (randomRIO)
import Numeric (showHex)
deviceId :: IO String
deviceId = sequence [zeros, zeros, bits, bits] >>= return . intercalate "-"
where zeros = return "00000000"
bits = randomRIO (0x10000000::Integer, 0xffffffff::Integer) >>= return . flip showHex ""
编辑:感谢评论,我的函数现在使用fmap,看起来像这样
deviceId :: IO String
deviceId = intercalate "-" <$> sequence [zeros, zeros, bits, bits]
where zeros = return "00000000"
bits = flip showHex "" <$> randomRIO (0x10000000::Integer, 0xffffffff::Integer)
零返回对我有意义,因为它清楚地表明我们正在操作IO字符串。谢谢。还有其他改进吗?
答案 0 :(得分:2)
您可以使用random-string包来处理随机值和渲染:
% git clone https://github.com/TomMD/random-string
Cloning into 'random-string'...
remote: Counting objects: 12, done.
remote: Total 12 (delta 0), reused 0 (delta 0), pack-reused 12
Unpacking objects: 100% (12/12), done.
% cd random-string
% cabal new-repl
Resolving dependencies...
> import Data.List
> let zeros = pure $ replicate 8 '0'
> let rnd = randomString (StringOpts Base16 4)
> (intercalate "-") <$> sequence [zeros,zeros,rnd,rnd]
也就是说,没有进口的解决方案与您已经拥有的解决方案非常相似:
f = intercalate "-" <$> sequence [z,z,r,r]
where z = pure (replicate 8 '0')
r = randomString (StringOpts Base16 4)
N.B。我的解决方案的范围与您的不同。我假设您选择了一个随机的0x10000000-0xFFFFFFFF只是因为您想要一个完整的渲染8个字符并且不想或知道如何渲染前导零。如果你想在范围内配对,那么随机字符串包可能比值更麻烦。
答案 1 :(得分:0)
您的代码与IO
紧密耦合,根据您的应用程序的设计,它可能不太实用。直觉上,IO动作只是产生随机种子所必需的,之后它就没用了。
deviceId :: RandomGen g => g -> String
我从来没有在Haskell中随机玩过,但我认为&#34;随机性&#34;是输入的定性属性,而不是输出的属性(如上面deviceId
的类型所示)。所以我想知道某个地方是否有随机Comonad,it turns out there is。
-- Generates random hex strings of length n
randomHexString :: RandomGen g => Int -> g -> [String]
randomHexString n = (extracts next =<= take n . extracts next) . mkRandR ('0', 'f')
现在deviceId
就像
deviceId g = intercalate "-" xss where
xss = zs ++ ws
zs = replicate 2 (replicate 8 '0')
ws = take 2 $ randomHexString 8 g
并且看不到IO。遗憾的是,comonad-random软件包已被弃用。
但是,您可能希望在世界末尾生成随机种子并在必要时传递它。