Haskell

时间:2018-05-08 16:32:42

标签: haskell

我对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字符串。谢谢。还有其他改进吗?

2 个答案:

答案 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软件包已被弃用。

但是,您可能希望在世界末尾生成随机种子并在必要时传递它。