80 votes

Convertit une Chaîne en Entier/flottant dans Haskell?

data GroceryItem = CartItem ItemName Price Quantity | StockItem ItemName Price Quantity

makeGroceryItem :: String -> Float -> Int -> GroceryItem
makeGroceryItem name price quantity = CartItem name price quantity  

Je veux créer un GroceryItem lors de l'utilisation d'une Chaîne de caractères ou [Chaîne]

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

L'entrée sera dans le format ["Apple","15.00","5"] qui j'ai rompu à l'aide de mots de fonction en haskell. Je reçois ce message d'erreur je pense que c'est parce que le makeGroceryItem accepte un Flotteur et un Int. Mais comment puis-je faire b et c Float et Int respectivement?

*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*

Merci beaucoup d'avance :)

100voto

KennyTM Points 232647

read peut analyser une chaîne en float et int:

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

Mais le problème (1) est dans votre modèle:

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

Ici, : est un (associatifs droit) opérateur binaire qui ajoute un élément à une liste. Le membre de droite d'un élément doit être une liste. Par conséquent, compte tenu de l'expression a:b:c, Haskell permettra de déduire les types suivants:

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

c'est à dire c sera considéré comme une liste de chaînes de caractères. Évidemment, il ne peut pas être read ou passé dans toutes les fonctions attend une Chaîne de caractères.

Au lieu de cela, vous devez utiliser

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

si la liste doit avoir exactement 3 éléments, ou

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

si ≥3 éléments est acceptable.

Aussi (2), l'expression

makeGroceryItem a read b read c

sera interprété comme makeGroceryItem en 5 arguments, dont 2 sont l' read fonction. Vous devez utiliser des parenthèses:

makeGroceryItem a (read b) (read c)

81voto

LukeN Points 3191

Même si ce n'est déjà fait, je vous suggère fortement de l'aide d' reads chaîne de conversion, parce qu'il est beaucoup plus sûr, comme il ne manque pas d'une exception irrécupérable.

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)]
[]

Sur le succès, il sera de retour une liste avec un seul élément, et un tuple composé de la valeur convertie et peut-être unconvertable des personnages supplémentaires, et en cas d'échec d'une liste vide. Il est facile de correspondance de modèle pour la réussite et l'échec, et il ne va pas exploser dans votre visage!

5voto

dave4420 Points 31298

Deux choses:

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

ou sinon

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

parce qu' : n'est pas le même que ++.

Pendant ce temps, sur le côté droit --- le côté qui est en vous donnant le message d'erreur que tu vois --- vous devez regrouper des expressions à l'aide de crochets. Sinon, parse est interprétée comme étant une valeur que vous souhaitez passer à l' makeGroceryItem, de sorte que le compilateur se plaint lorsque vous essayez de passer les 5 arguments à une fonction qui ne prend que 3 paramètres.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X