【问题标题】:Main function input for RealFloat in haskellhaskell 中 RealFloat 的主要函数输入
【发布时间】:2017-11-03 21:09:42
【问题描述】:

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

【问题讨论】:

  • Haskell 中的函数调用不需要参数周围的括号或参数之间的逗号。将bmiTell( read weight ::Float, read height ::Float) 更改为bmiTell (read weight :: Float) (read height :: Float)
  • 谢谢,它有效。您能否提供任何资源让我可以了解有关 Haskell IO 的更多信息
  • 这个问题与IO无关。我没有任何特别的建议,但Haskell tag wiki 确实提供了一些您可能会觉得有用的信息。

标签: haskell io main


【解决方案1】:

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

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 -&gt; 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!),这可以通过使用方便的 no-op $ 运算符来完成:

    print $ bmiTell (read weight) (read height)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-12
    • 1970-01-01
    • 1970-01-01
    • 2019-05-20
    • 2020-03-19
    相关资源
    最近更新 更多