haskell 中 RealFloat 的主要函数输入

Main function input for RealFloat in haskell

我正在尝试制作一个接受 2 个 Realfloat 输入并通过此函数的主函数

bmiTell :: (RealFloat a) => a -> a -> String  
bmiTell weight height  
    | bmi <= 18.5 = "You're underweight"
    | bmi <= 25.0 = "You're normal"
    | bmi <= 30.0 = "You're overweight"
    | otherwise = "You're obese"
    where bmi = weight / height ^ 2  

我的解决方案是,我尝试获取体重和身高并将其传递给 bmiTell 函数

main = do
    putStrLn "What's your weight?"  
    weight <- getLine  
    putStrLn "What's your height?"  
    height <- getLine
    print (bmiTell( read weight ::Float, read height ::Float))

这就是错误

* No instance for (Show ((Float, Float) -> String))
        arising from a use of `print'
        (maybe you haven't applied a function to enough arguments?)
    * In a stmt of a 'do' block:
        print (bmiTell (read weight :: Float, read height :: Float))
      In the expression:
        do putStrLn "What's your weight?"
           weight <- getLine
           putStrLn "What's your height?"
           height <- getLine
           ....
      In an equation for `main':
          main
            = do putStrLn "What's your weight?"
                 weight <- getLine
                 putStrLn "What's your height?"
                 ....
   |
14 |     print (bmiTell( read weight ::Float, read height ::Float))
   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

getbmi.hs:14:12: error:
    * No instance for (RealFloat (Float, Float))
        arising from a use of `bmiTell'
    * In the first argument of `print', namely
        `(bmiTell (read weight :: Float, read height :: Float))'
      In a stmt of a 'do' block:
        print (bmiTell (read weight :: Float, read height :: Float))
      In the expression:
        do putStrLn "What's your weight?"
           weight <- getLine
           putStrLn "What's your height?"
           height <- getLine
           ....
   |
14 |     print (bmiTell( read weight ::Float, read height ::Float))
   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

我知道 RealFloat 是 Double 或 Float。任何人都可以如何获取 RealFloat 的输入并通过函数传递它。

为简单起见,我将在下面讨论您函数的单态版本,即

bmiTell :: Double -> Double -> String

(对于 RealFloat,类型 Doubleusually the only sensible choice。)


如果您定义了

,您的代码将实际运行
bmiTell :: (Double, Double) -> String  
bmiTell(weight, height)
  | ...

这将是定义多参数函数的“正常方式”,因为大多数其他编程语言都会这样做。在这种情况下 bmiTell (read weight, read height) 会起作用。

可以 在 Haskell 中执行此操作,但是我们更喜欢一种不同的样式,它在许多方面是等效的,但提供了一些很好的优势,尽管它经常令人困惑初学者:我们 Curry 大多数多参数函数。

可以很简单地解释:不是在元组中一次提供两个参数,而是提供第一个参数,然后提供下一个。等等。所以,你有函数 bmiTell。你给它参数 w,即你写 bmiTell w。然后你还给它参数h,所以你写(bmiTell w) h,解析器允许我们省略括号。

函数因此具有签名 bmiTell :: Double -> SOMETHING,其中 SOMETHING 必须能够接受另一个参数...然后才给出一个字符串。所以,其实

bmiTell :: Double -> (Double -> String)

这里也是特意选择了解析规则,因此我们实际上可以省略括号。

要使用该函数,你必须,好吧——一个一个地给出两个参数。

    bmiTell (read weight) (reight height)

整个节目中:

main :: IO ()
main = do
    putStrLn "What's your weight?"  
    weight <- getLine  
    putStrLn "What's your height?"  
    height <- getLine
    print (bmiTell (read weight) (read height))

实际上我们喜欢省略更多的括号(我们不是 Lispers!),这可以通过使用方便的空操作 $ 运算符来完成:

    print $ bmiTell (read weight) (read height)