1. ホーム
  2. haskell

Haskellで文字列を整数/浮動小数点に変換する?

2023-08-30 17:49:23

質問

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

入力は以下のような形式になります。 ["Apple","15.00","5"] という形式で、これをHaskellの words 関数を使って分割しました。

以下のようなエラーが出ますが、これは makeGroceryItemFloatInt .

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

しかし、どのようにすれば bc 型の FloatInt というように、それぞれ?

どのように解決するのですか?

read は、文字列を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) = ...

ここで : は(右結合)二項演算子で、リストに要素を前置します。要素の右辺はリストでなければなりません。従って、次の式が与えられると a:b:c という式が与えられると、Haskellは次のような型を推論します。

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

すなわち c は文字列のリストとみなされます。明らかに、それは read であったり、文字列を期待する関数に渡されることはありません。

代わりに

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

リストがちょうど3つの項目を持たなければならない場合、または

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

の場合、≧3項目が許容されます。

また、(2)では、式

makeGroceryItem a read b read c

は、次のように解釈されます。 makeGroceryItem は5つの引数を取り、そのうちの2つは read という関数がある。括弧を使用する必要があります。

makeGroceryItem a (read b) (read c)