如何在 Haskell 中将 IO Double 用作常规 Double

How to use IO Double as regular Double in Haskell

我必须遵循以下代码

isInCircle::Double->Double->Bool
isInCircle p1 p2 = sqrt((p1*p1)+(p2*p2)) <= 1

当我打电话时

isInCircle (random :: Double) (random :: Double)

我收到这个错误

* Couldn't match expected type `Double' with actual type `g0 -> (a0, g0)'

如果我将 isInCircle 函数的参数更改为 IO Double,我会收到 sqrt 和加法错误...

你能帮帮我吗?我的代码:

import System.Random 
main :: IO () 
main = do 
    if isInCircle (random :: Double) (random :: Double) 
    then print "True" 
    else print "False" 

isInCircle::Double->Double->Bool 
isInCircle p1 p2 = sqrt((p1*p1)+(p2*p2)) <= 1

在 GHCi 提示符下查看,

> :i Random
class Random <b>a</b> 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
  <i>randomIO  :: IO <b>a</b></i>
        -- 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 <b>Double</b> -- Defined in `System.Random'
instance Random Char -- Defined in `System.Random'
instance Random Bool -- Defined in `System.Random'

我们看到 random 而不是 Double<i>randomIO :: IO <b>Double</b></i> 看起来更有希望。如果我们能以某种方式获得 Double "inside" IO Double 类型的 "value" 就好了。我们能做到吗?

是的,我们可以。这就是 "bind" 的用途。在 do 符号中,它是用 <-:

完成的
import System.Random 
main :: <b>IO</b> () 
main = do 
    -- if isInCircle (random :: Double) (random :: Double) 
    <i>x</i> <- (randomIO :: <b>IO</b> Double)   -- thus, x :: Double
    <i>y</i> <- (randomIO :: <b>IO</b> Double)   -- thus, y :: Double
    <i>if isInCircle x y</i>
      <i>then</i> print "True"            -- print "True" :: <b>IO</b> ()
      <i>else</i> print "False"           -- (if ... ...) :: <b>IO</b> ()

pure 函数 isInCircle 本身没有改变,也不需要改变。它仍然是对两个纯值进行运算的 pure 函数。但是我们将它嵌入一个组合的IO计算方法,由更小的IO计算方法构建(包括"built-in"randomIO方法)这样,当执行结果组合(组合?)计算时 - 由名为 main 的值引用/描述 - 执行时,它将 使用 函数 inInCircle 与通过两个 randomIOs.

获得的两个值

那是 Haskell。纯粹的内部,I/O 在外部(如果不是,它还能如何与我们沟通 – 根据定义 – 通过 I/O)。