将string转换为整数/浮点在Haskell?
data GroceryItem = CartItem ItemName Price Quantity | StockItem ItemName Price Quantity makeGroceryItem :: String -> Float -> Int -> GroceryItem makeGroceryItem name price quantity = CartItem name price quantity
我想在使用String或[String]时创build一个GroceryItem,
createGroceryItem :: [String] -> GroceryItem createGroceryItem (a:b:c) = makeGroceryItem abc
input的格式是[“Apple”,“15.00”,“5”],我使用haskell中的单词函数进行分解。 我得到这个错误,我认为是因为makeGroceryItem接受一个浮点数和一个整数。 但是,我如何分别做b和c Float和Int?
*Type error in application *** Expression : makeGroceryItem a read b read c *** Term : makeGroceryItem *** Type : String -> Float -> Int -> GroceryItem *** Does not match : a -> b -> c -> d -> e -> f*
read
可以将一个stringparsing为float和int:
Prelude> :set +t Prelude> read "123.456" :: Float 123.456 it :: Float Prelude> read "123456" :: Int 123456 it :: Int
但问题(1)是在你的模式:
createGroceryItem (a:b:c) = ...
这里:
是一个(右联合)二元运算符,它将一个元素前置到一个列表中。 元素的RHS必须是一个列表。 因此,给定expression式a:b:c
,Haskell将推断以下types:
a :: String b :: String c :: [String]
即c
将被认为是一个string列表。 很明显,它不能被read
或传递给期望String的任何函数。
相反,你应该使用
createGroceryItem [a, b, c] = ...
如果列表必须有3个项目,或者
createGroceryItem (a:b:c:xs) = ...
如果≥3项是可以接受的。
还有(2),expression式
makeGroceryItem a read b read c
将被解释为makeGroceryItem
取5个参数,其中2个是read
函数。 你需要使用括号:
makeGroceryItem a (read b) (read c)
即使这已经完成,我强烈build议使用reads
string转换,因为它更安全,因为它不会因不可恢复的exception而失败。
reads :: (Read a) => String -> [(a, String)] Prelude> reads "5" :: [(Double, String)] [(5.0,"")] Prelude> reads "5ds" :: [(Double, String)] [(5.0,"ds")] Prelude> reads "dffd" :: [(Double, String)] []
成功时,它将返回一个只包含一个元素的列表,以及一个由转换后的值组成的元组,以及可能不可转换的额外字符,失败时则返回一个空列表。 模式匹配成功和失败很容易,它不会炸毁你的脸!
两件事情:
createGroceryItem [a, b, c] = makeGroceryItem a (parse b) (parse c) -- pattern match error if not exactly 3 items in list
或者可选地
createGroceryItem (a : b : c : _) = makeGroceryItem a (parse b) (parse c) -- pattern match error if fewer than 3 items in list, ignore excess items
因为:
和++
不一样。
同时在右侧—给你错误信息的一面—你必须用括号将expression式分组。 否则, parse
被解释为一个你想传递给makeGroceryItem
的值,所以当你试图传递5个参数给一个只有3个参数的函数时,编译器会抱怨。
filterNumberFromString :: String -> String filterNumberFromString s = let allowedString = ['0'..'9'] ++ ['.', ','] toPoint n | n == ',' = '.' | otherwise = n f = filter (`elem` allowedString) s d = map toPoint f in d convertStringToFloat :: String -> Float convertStringToFloat s = let betterString = filterNumberFromString s asFloat = read betterString :: Float in asFloat print (convertStringToFloat "15,00" + 1)
– >打印16.0
多数民众赞成我是如何解决这个任务在我的项目。