在Haskell中将字符串转换为Integer/Float?

Ran*_*ray 68 floating-point int 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 a `String` or `[String]`

createGroceryItem :: [String] -> GroceryItem
createGroceryItem (a:b:c) = makeGroceryItem a b c
Run Code Online (Sandbox Code Playgroud)

输入将采用["Apple","15.00","5"]我使用Haskell words函数分解的格式.

我得到以下错误,我认为是因为makeGroceryItem接受a Float和an 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*
Run Code Online (Sandbox Code Playgroud)

但我怎么做bc类型Float,并Int分别?

ken*_*ytm 86

read 可以将字符串解析为float和int:

Prelude> :set +t
Prelude> read "123.456" :: Float
123.456
it :: Float
Prelude> read "123456" :: Int
123456
it :: Int
Run Code Online (Sandbox Code Playgroud)

但问题(1)在你的模式中:

createGroceryItem (a:b:c) = ...
Run Code Online (Sandbox Code Playgroud)

:是一个(右关联)二元运算符,它将元素添加到列表中.元素的RHS必须是列表.因此,给定表达式a:b:c,Haskell将推断以下类型:

a :: String
b :: String
c :: [String]
Run Code Online (Sandbox Code Playgroud)

ie c将被视为字符串列表.显然它不能read或传递给任何期望String的函数.

相反,你应该使用

createGroceryItem [a, b, c] = ...
Run Code Online (Sandbox Code Playgroud)

如果列表必须有3个项目,或者

createGroceryItem (a:b:c:xs) = ...
Run Code Online (Sandbox Code Playgroud)

如果≥3项是可以接受的.

还有(2),表达

makeGroceryItem a read b read c
Run Code Online (Sandbox Code Playgroud)

将被解释为makeGroceryItem采用5个参数,其中2个是read函数.你需要使用括号:

makeGroceryItem a (read b) (read c)
Run Code Online (Sandbox Code Playgroud)


Luk*_*keN 76

即使这个问题已经有了答案,我强烈建议使用reads字符串转换,因为它更安全,因为它不会因不可恢复的异常而失败.

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)]
[]
Run Code Online (Sandbox Code Playgroud)

成功时,reads返回一个只包含一个元素的列表:由转换后的值组成的元组,也可能是不可转换的额外字符.失败时,reads返回一个空列表.

成功和失败的模式匹配很容易,它不会在你脸上爆炸!

  • 从base-4.6开始,有[`readMaybe :: Read a => String - > Maybe a`](http://hackage.haskell.org/package/base-4.9.0.0/docs/Text-Read.html# v:readMaybe)在`Text.Read`中,这比在这种情况下使用`reads`更方便. (10认同)

dav*_*420 5

两件事情:

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

或者

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

因为:不一样++.

同时在右侧---给你看错误信息的那一面---你必须使用括号对表达式进行分组.否则parse被解释为您要传递给的值makeGroceryItem,因此当您尝试将5个参数传递给只接受3个参数的函数时,编译器会抱怨.