リストを操作する関数(その2)

zip は2つのリストからそれぞれの要素を取り出して,タプル(組)にしたリストを返す。

Prelude> zip [1,2,3] "abc"
[(1,'a'),(2,'b'),(3,'c')]

タプルには違う型を含めることができる。
zipWith はタプルを作る代わりに関数を適用する。

Prelude> zipWith (+) [1,2,3] [10,20,30]
[11,22,33]

上の例では + を zipWith の第1引数と渡しているけど,()で囲んでやらないとエラーになる。
うまく zipWith の引数として認識できないってことかな。

Prelude> zipWith + [1,2,3] [10,20,30]
<interactive>:1:10:
Couldn't match `[a]' against `t -> t1'
Expected type: [a]
Inferred type: t -> t1
Probable cause: `[1, 2, 3]' is applied to too many arguments in the call
([1, 2, 3] [10, 20, 30])
In the second argument of `(+)', namely `[1, 2, 3] [10, 20, 30]'

ところでタプルって何に使うんだろ。

追記: zipWith の引数について
こうすると同じメッセージがでる。つまり二つのリストが zipWith ではなく + の引数だと解釈されてしまうってことか。

Prelude> zipWith (+ [1,2,3] [10,20,30])
<interactive>:1:11:
Couldn't match `[a]' against `t -> t1'
Expected type: [a]
Inferred type: t -> t1
Probable cause: `[1, 2, 3]' is applied to too many arguments in the call
([1, 2, 3] [10, 20, 30])
In the second argument of `(+)', namely `[1, 2, 3] [10, 20, 30]'

リストと値の型

ひとつのリスト中に違う型の値を含めることはできない。

Prelude> [1,2,'a']
<interactive>:1:1:
    No instance for (Num Char)
      arising from the literal `1' at <interactive>:1:1
    Probable fix: add an instance declaration for (Num Char)
    In the list element: 1
    In the definition of `it': it = [1, 2, 'a']

当然連結もダメ。

Prelude> [1,2,3] ++ ['a','b','c']
<interactive>:1:1:
    No instance for (Num Char)
      arising from the literal `1' at <interactive>:1:1
    Probable fix: add an instance declaration for (Num Char)
    In the list element: 1
    In the first argument of `(++)', namely `[1, 2, 3]'
    In the definition of `it': it = [1, 2, 3] ++ ['a', 'b', 'c']

リストを操作する関数

head はリストの先頭の要素,tail は先頭以外の要素を返す。

Prelude> head [1,2,3,4,5]
1
Prelude> tail [1,2,3,4,5]
[2,3,4,5]

最後の要素を得るには last が使える。

Prelude> last "abc"
'c'

文字列にも使える。

Prelude> head "abc"
'a'

演算子も関数。 !! でインデックスに対応する要素を返し,++ でリストを連結。

Prelude> "abcde" !! 3
'd'
Prelude> "abc" ++ "ef"
"abcef"

文字と文字列、リスト

‘(シングルクォート)’でかこむ文字はChar型。

Prelude> :type 'a'
'a' :: Char

“(ダブルクォート)”でかこんだ文字列はChar型のリスト。[]でかこまれてるのがリストのしるし。

Prelude> :type "abc"
"abc" :: [Char]
Prelude> :type ['a','b','c']
['a','b','c'] :: [Char]
Prelude> :type "a"
"a" :: [Char]

なるほど。””でかこめば1文字でも要素ひとつのリストってわけか。
文字列を”でかこむとエラーになる。

Prelude> :type 'abc'
<interactive>:1:1: lexical error in string/character literal

GHCi

GHCiは対話的に操作できるインタプリタ。:help コマンドで使い方がわかる。

>ghci
   ___         ___ _
  / _ \ /\  /\/ __(_)
 / /_\// /_/ / /  | |      GHC Interactive, version 6.4.1, for Haskell 98.
/ /_\\/ __  / /___| |      http://www.haskell.org/ghc/
\____/\/ /_/\____/|_|      Type :? for help.

Loading package base-1.0 ... linking ... done.
Prelude> :help
 Commands available from the prompt:
   <stmt>                      evaluate/run <stmt>
   :add <filename> ...         add module(s) to the current target set
   :browse [*]<module>         display the names defined by    <module>
   :cd <dir>                   change directory to <dir>
   :def <cmd> <expr>           define a command :<cmd>
   :help, :?                   display this list of commands
   :info [<name> ...]          display information about the given  names
   :load <filename> ...        load module(s) and their dependents
   :module [+/-] [*]<mod> ...  set the context for expression evaluation
   :reload                     reload the current module set
   :set 

終了するには :quit。

関数の定義はできない。別途ファイルに保存して、:load コマンドで読み込む。

Prelude> :l addone.hs
Compiling Main             ( addone.hs, interpreted )
Ok, modules loaded: Main.
*Main> addOne 3
4

Hello world.

まずはこれだな。

main = putStr "Hello world. This is Haskell!\n"

標準出力へ文字を出力するのは putStr 関数。
main = は代入ではない。Haskell に代入はない。これは main 関数の定義をしている。

GHC はコンパイラなのでまずはコンパイルから。

>ghc -o hello hello.hs

-oオプションで実行ファイルの名前を指定できる(指定しないとmain.exe)。
さて実行しよう。

>hello.exe
Hello world. This is Haskell!

はろー。

関数型言語

関数型言語というものに興味があった。
あっただけで今まで調べもしなかったんだけど,ちょうど良さそうな本を発見。つい買ってしまう。
[amazonjs asin=”4839919623″ locale=”JP” title=”入門Haskell―はじめて学ぶ関数型言語”]
ちょっとずつやってみよう。