HaskellのStringからIntへの変換

AtCoderで問題を解いてる時に、HaskellでStringからIntへの変換がわからくて困った。確かこれはujihisaさんに教えてもらったようなそうでなかったような...。とにかくメモとして残しておく。

StringからIntへの変換方法

Haskellで文字列StringをIntなどの整数に変換するにはこんな風にする。「read 引数 :: 型名」で変換したい型に変換するらしい。

Prelude> read "123" :: Int
Prelude> 123

形名を付けないとこんなエラーが出る

Prelude> read "123"

<interactive>:8:1:
    Ambiguous type variable `a0' in the constraint:
      (Read a0) arising from a use of `read'
    Probable fix: add a type signature that fixes these type variable(s)
    In the expression: read "123"
    In an equation for `it': it = read "123"

関数にしておく場合は、例えばこういう風にしとくといいかも。関数にするほどではないものではある。

-- rInt.hs
rInt :: String -> Int
rInt str = read str :: Int  -- rInt 多分 read Int の略?
string2int str = read str :: Int -- string2int → string to int の略

インタプリタで関数定義する場合はletで関数を定義して使う。

Prelude> let string2Int str = read str :: Int
Prelude> string2Int "123"
->123

これはFloatとかでも同じように適用できる。

-- rFloat.hs
rFloat str = read str :: Float
main = undefined
Prelude> :l rFloat.hs
Prelude> rFloat "20"
-> 20.0

main中のdo部分ではIOモナドになっているので、letで値を束縛しておくと使いやすくなるはず。

-- string2int.hs
import Text.Printf (printf)

string2int str = read str :: Int
myDouble x = x * x

main = do
  putStr "input number : "
  s <- getLine
  let s1 = string2int s
  print $ myDouble s1
  printf "%d\n" (myDouble s1)
Prelude> :l string2int.h
Prelude> main
-> input number : 6
36
36

main関数内はIOなのでprintputStr,printfなどのIOモナドの関数で終わらないといけない。
showの最終的な型は String になる。これは、IO Stringではないのでエラーになってしまう。

C言語でよく使うprintfも使うことができる。printfはC言語での使い方と同じで、

// C言語
printf("%s %d %d\n","123",123,s1)
-- Haskell
printf "%s %d %d\n" "123" 123 s1

似たような書式で使える。詳しいことは検索して調べてください。

つぶやき

AtCoderですらすら問題が解けるのはいつになるのか...。

メモ

関数
read Read a => String -> a
print print :: Show a => a -> IO ()
show show :: Show a => a -> String
printf printf :: Text.Printf.PrintfType r => String -> r

追記 2013/7/10

read "123"の場合のエラーを追加