haskell中RealFloat的主要功能输入

时间:2017-11-03 21:09:43

标签: haskell io main

我正在尝试创建一个主函数,它需要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的输入并通过函数传递它。

1 个答案:

答案 0 :(得分:3)

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

bmiTell :: Double -> Double -> String

(对于RealFloatDouble类型为usually 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)