Fork me on GitHub

first randoms . split函数的类型问题

在GHCi里面查到的函数类型:

split :: RandomGen g => g -> (g, g)

randoms :: (RandomGen g, Random a) => g -> [a]

(randoms.split):: (RandomGen g, RandomGen (g, g), Random a) => g -> [a]

这里g是RandomGen类型,(g, g)也是RandomGen类型?
这个我还能一知半解,只是期待高人详解一下RandomGen。但是跟Control.Arrow (first)组合起来:

(first randoms) :: (RandomGen g, Random a) => (g, d) -> ([a], d)

(first randoms . split) :: (RandomGen g, Random a) => g -> ([a], g)

既然randoms和 randoms . split的类型都是 g -> [a],那么前面加个first,应该都是 (g, d) -> ([a], d)啊,为什么(first randoms . split)类型居然是 g -> ([a], g)?

Submitted by at 6 years ago

所有回复

关于第二问,是优先级的问题吧

:t first (randoms . split) 
:: (RandomGen b, RandomGen (b, b), Random a) => (b, d) -> ([a], d)
:t first randoms . split
:: (RandomGen d, Random a) => d -> ([a], d)

wuhaisheng 6 years ago

多谢!

peidge 6 years ago

split 出来的 (g, g) 是说把一个 RandomGen 劈开变两个,这样可以分开使用,因为 RandomGen 是纯函数。

比较

let xs = randoms g
    ys = randoms g
in xs == ys

let (g1, g2) = split g
    xs = randoms g1
    ys = randoms g2
in xs == ys

前者返回 True,后者返回 False

ninegua 6 years ago

准确一点,是对 RandomGen 的操作都是纯函数。

ninegua 6 years ago

hmm... 似乎真运行起来都不会中止哈,应该 x = take 10 $ randoms .. 这样

ninegua 6 years ago