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

4
我有以下的代码:
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

1
我无法重现您提供的代码中出现的错误,因此无法帮助您。您必须包含实际导致该错误的代码。请阅读有关 MCVE 的内容。 - AJF
导入 System.Randommain :: 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 - EvilGenius
4
请勿在评论区发布更新内容,请通过编辑您的问题来进行修改。 - n. m.
5
一个IO Double不是一个数字,而是生成一个数字的配方(或“操作”)的意思。 - melpomene
@luqui它之所以为-2,是因为在编辑之前,它没有提供足够的信息,因此无法回答。 - AJF
1个回答

7

在 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'

我们可以看到,对于Double,与其使用random,使用randomIO :: IO Double更加有前途。只要我们能够以某种方式获取“值”中的Double,那么我们就可以做到了。

是的,我们可以。这正是“绑定”所用之处。在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> ()

这里的纯函数 isInCircle 本身没有被改变,也不需要改变。它仍然是作用于两个纯值的同一个纯函数。但我们将其嵌入到一个由小型 IO 计算配方组成的组合 IO 计算配方中(包括“内置”的 randomIO 配方),以便在执行生成的组合(复合?)计算 - 指通过名为 main 的值引用/描述的计算时,将使用 inInCircle 纯函数与通过两个 randomIO 获得的两个值。

这就是 Haskell。从内部来看是纯函数,从外部来看是 I/O(如果不是这样 - 就是根据定义 - 它如何与我们通信呢?)。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接