在 GHCi 提示符下检查它,
> :i Random
class Random a where
randomR :: RandomGen g => (a, a) -> g -> (a, g)
random :: RandomGen g => g -> (a, g)
randomRs :: RandomGen g => (a, a) -> g -> [a]
randoms :: RandomGen g => g -> [a]
randomRIO :: (a, a) -> IO a
randomIO :: IO a
-- Defined in `System.Random'
instance Random Integer -- Defined in `System.Random'
instance Random Int -- Defined in `System.Random'
instance Random Float -- Defined in `System.Random'
instance Random Double -- Defined in `System.Random'
instance Random Char -- Defined in `System.Random'
instance Random Bool -- Defined in `System.Random'
我们看到代替random
, for Double
,看起来更有希望。如果我们能以某种方式在“内部”获得“价值”的类型。我们能做到吗?randomIO :: IO Double
Double
IO Double
我们可以。这就是“绑定”的用途。在do
符号中,它是通过以下方式完成的<-
:
import System.Random
main :: IO ()
main = do
-- if isInCircle (random :: Double) (random :: Double)
x <- (randomIO :: IO Double) -- thus, x :: Double
y <- (randomIO :: IO Double) -- thus, y :: Double
if isInCircle x y
then print "True" -- print "True" :: IO ()
else print "False" -- (if ... ...) :: IO ()
纯函数本身没有改变,isInCircle
也不需要改变。它仍然是对两个纯值进行操作的同一个纯函数。但是我们将它嵌入到组合IO
计算配方中,该配方由较小IO
的计算配方(包括“内置”randomIO
配方)构建,这样当执行结果组合(组合?)计算 - 由命名值引用/描述main
- 时,它将使用通过两个s获得的两个值的纯函数。inInCircle
randomIO
那是哈斯克尔。内部纯粹,外部 I/O(如果不是——根据定义——通过 I/O ,它怎么能与我们通信)。