将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议使用readsstring转换,因为它更安全,因为它不会因不可恢复的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

多数民众赞成我是如何解决这个任务在我的项目。