Convert String to Integer / Float in Haskell?

data GroceryItem = CartItem ItemName Price Quantity | StockItem ItemName Price Quantity makeGroceryItem :: String -> Float -> Int -> GroceryItem makeGroceryItem name price quantity = CartItem name price quantity 

I want to create a GroceryItem when using String or [String]

 createGroceryItem :: [String] -> GroceryItem createGroceryItem (a:b:c) = makeGroceryItem abc 

The input will be in the format ["Apple", "15.00", "5"], which I broke using the haskell word function. I get this error, which, in my opinion, is due to the fact that makeGroceryItem accepts Float and Int. But how do I do b and c Float and Int, respectively?

 *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* 
+60
floating-point int haskell monads
Mar 18
source share
4 answers

read can parse a string into float and int:

 Prelude> :set +t Prelude> read "123.456" :: Float 123.456 it :: Float Prelude> read "123456" :: Int 123456 it :: Int 

But the problem (1) is in your template:

 createGroceryItem (a:b:c) = ... 

Here : is a (right-associative) binary operator that adds an item to the list. RHS item must be a list. Therefore, given the expression a:b:c , Haskell will infer the following types:

 a :: String b :: String c :: [String] 

i.e. c will be considered as a list of strings. Obviously, it cannot be read or passed to any functions that expect String.

You should use instead

 createGroceryItem [a, b, c] = ... 

if the list should have exactly 3 elements or

 createGroceryItem (a:b:c:xs) = ... 

if valid ≥3.

Also (2) expression

 makeGroceryItem a read b read c 

will be interpreted as makeGroceryItem using 5 arguments, 2 of which are read functions. You need to use brackets:

 makeGroceryItem a (read b) (read c) 
+75
Mar 18 2018-10-18T00:
source share

Despite the fact that this has already been done, I highly recommend using reads to convert strings, because it is much safer because it does not interrupt with an unrecoverable 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)] [] 

If successful, it will return a list with only one element and a tuple consisting of a converted value and possibly non-convertible additional characters, and if it fails, an empty list. It is easy to match the pattern for success and failure, and it will not explode in your face!

+72
Mar 21
source share

Two things:

 createGroceryItem [a, b, c] = makeGroceryItem a (parse b) (parse c) -- pattern match error if not exactly 3 items in list 

or alternatively

 createGroceryItem (a : b : c : _) = makeGroceryItem a (parse b) (parse c) -- pattern match error if fewer than 3 items in list, ignore excess items 

since : does not match with ++ .

Meanwhile, on the right side --- the side that gives you the error message you see --- you need to group the expressions with parentheses. Otherwise, parse interpreted as the value you want to pass to makeGroceryItem , so the compiler complains when you try to pass 5 arguments to a function that takes only 3 parameters.

+5
Mar 18 '10 at 9:01
source share
 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) 

-> prints 16.0

This is how I solved this problem in my project.

0
Aug 09 '17 at 8:42 on
source share



All Articles