Как ввести одно целое число с консоли
Придумал себе задачу на базовые элементы языка - "перевести температуру из градусов цельсия в фаренгейты", запнулся на этапе ввода целого числа:
-- Ask temperature in Celsius then convert to Fahrenheit
temperatureFahrenheit temperatureCelsius = 32 + temperatureCelsius * 9 / 5
main = do
putStrLn "What is temperature in Celsius?"
c <- getLine
let temperatureCelsius = (read c :: Int)
result <- temperatureFahrenheit temperatureCelsius
putStrLn ("It's " ++ result ++ " in Fahrenheit")
Получаю ошибку компиляции (под рукой нет установленного haskell, это вывод с ideone.com):
[1 of 1] Compiling Main ( prog.hs, prog.o ) prog.hs:8:30: error: • Couldn't match type ‘[Char]’ with ‘Int’ Expected type: Int Actual type: String • In the expression: c :: Int In an equation for ‘temperatureCelsius’: temperatureCelsius = c :: Int In the expression: do putStrLn "What temperature in Celsius?" c <- getLine let temperatureCelsius = ... result <- temperatureFahrenheit temperatureCelsius .... | 8 | let temperatureCelsius = c :: Int | ^ prog.hs:9:15: error: • Couldn't match expected type ‘IO [Char]’ with actual type ‘Int’ • In a stmt of a 'do' block: result <- temperatureFahrenheit temperatureCelsius In the expression: do putStrLn "What temperature in Celsius?" c <- getLine let temperatureCelsius = ... result <- temperatureFahrenheit temperatureCelsius .... In an equation for ‘main’: main = do putStrLn "What temperature in Celsius?" c <- getLine let temperatureCelsius = ... .... | 9 | result <- temperatureFahrenheit temperatureCelsius | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Что не так? Мне нужно взять строку, получить на выходе Int - так это по крайней мере мне видится в терминах скажем c#.
Что пытался делать:
- похожий пример есть на en so: https://stackoverflow.com/a/42214447/5752652
- видел примеры на использование Parsec, но мне показалось это из пушки по воробьям - я осваиваю базу, потому хотелось бы без сторонних библиотек, тем более мне не нужны пока числа через пробел - тут с одним бы разобраться
- читал про устройство типов в IO https://habr.com/en/post/153383/#hell-difficulty-part но пока в голове не укладывается как это использовать
- читал про readLn описание https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:readLn покрутил так и эдак разные варианты кода - тож не заработало
- ну и просто всякие буквари читал типа http://learnyouahaskell.com/chapters и https://learnxinyminutes.com/docs/haskell/ на предмет общего синтаксиса
Ответы (2 шт):
Ошибки три
- над
temperatureCelsiusпроизводится операция деления, она доступна только для дробных типов (представителей классаFractional), но не дляInt. Либо меняйте тип наDouble, либо используйте целочисленное делениеdivилиquot, либо явно приводите типы. temperatureFahrenheit temperatureCelsiusне IO-действие, здесь нужно использоватьlet result = ...вместоresult <- ...- операция
++конкатенирует строки а не числа со строками. используйтеshowдля получения строкового представления числа.
Так, варианты в целых числах (допустим, перевод цельсий -> кельвин).
Через getLine:
-- Ask temperature in Celsius then convert to Kelvin
temperatureKelvin temperatureCelsius = temperatureCelsius + 273
main = do
putStrLn "What is temperature in Celsius?"
c <- getLine
let temperatureCelsius = (read c :: Int)
let result = temperatureKelvin temperatureCelsius
putStrLn ("It's " ++ show result ++ " in Kelvin")
Через readLn:
-- Ask temperature in Celsius then convert to Kelvin
temperatureKelvin temperatureCelsius = temperatureCelsius + 273
main = do
putStrLn "What is temperature in Celsius?"
c <- readLn
let result = temperatureKelvin c
putStrLn ("It's " ++ show result ++ " in Kelvin")
И допустим надо ввести два числа, одно целое, одно рациональное. Скажем, расчёт ИМТ:
-- Ask mass and height, then calculate BMI (body mass index)
-- Result for mass = 77 and height = 1.70 is 26.643598615916957
bmi mass height = mass / (height * height)
main = do
putStrLn ("Enter your mass in kilos")
mass <- readLn
putStrLn ("Enter your height in meters")
h <- getLine
let height = (read h :: Double)
let result = bmi mass height
putStrLn ("Your body mass index is " ++ show result)
Спасибо @extrn за указание на ошибки: когда их сразу больше одной -- непросто понять, почему никак к ответу не получается придти.