如何在 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
与通过两个 randomIO
s.
获得的两个值
那是 Haskell。纯粹的内部,I/O 在外部(如果不是,它还能如何与我们沟通 – 根据定义 – 通过 I/O)。
我必须遵循以下代码
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
与通过两个 randomIO
s.
那是 Haskell。纯粹的内部,I/O 在外部(如果不是,它还能如何与我们沟通 – 根据定义 – 通过 I/O)。