2006-09-22Haskellでよかった
■ 第6章 基本的な値 - リスト
ワリと序盤から出てきたリストについては、ここではそれほど新しいトピックはないかな。多分おさえておくべきは「:」(コロン)演算子。
main = do
print (1:2:3:[])
print (1:2:(3:[]))
print (1:2:[3])
print (1:(2:[3]))
print (1:[2,3])
print ([1,2,3])
>colon [1,2,3] [1,2,3] [1,2,3] [1,2,3] [1,2,3] [1,2,3]
これはこれで良いのだけれども、printの引数を括弧でくくらないとエラーになるのはナゼだろう。
colon.hs:3:12:
Couldn't match `[]' against `IO'
Expected type: []
Inferred type: IO
In a 'do' expression: print (1 : (2 : (3 : [])))
In the definition of `main':
main = do
(print 1) : (2 : (3 : []))
print (1 : (2 : (3 : [])))
print (1 : (2 : [3]))
print (1 : (2 : [3]))
print (1 : [2, 3])
print ([1, 2, 3])
2006-09-18久々のHaskell
■ 第6章 基本的な値 - 数値
ここからは難しくなりそうなので、細かいところを確かめつつやっていこうかと。まずは数値について。
IntとIntegerが違うってホント?
a = (16::Integer) b = (3::Int) c = a+b main = print c
IntOrInteger.hs:3:6:
Couldn't match `Integer' against `Int'
Expected type: Integer
Inferred type: Int
In the second argument of `(+)', namely `b'
In the definition of `c': c = a + b
あら、ホントだ。どうにかしてくれても良さそうなもんだけど、Haskellの型はかなり厳密なものらしい。
でも、
a = (16::Integer) main = print (a+3)
19
これはOK。つまり、数値リテラルは文脈によって変換されるけど、一旦型を決めてしまうとIntとIntegerですら互換性がないみたい。
リテラルだけど型を付けてやると、
a = (16::Integer) main = print (a+(3::Int))
IntOrInteger.hs:2:17:
Couldn't match `Integer' against `Int'
Expected type: Integer
Inferred type: Int
In the expression: 3 :: Int
In the second argument of `(+)', namely `(3 :: Int)'
怒られる。
■ 基本的な値 - 文字列
文字といったらChar。文字列といったら[Char]。[Char]の別名はString。これは結構分かりやすい。JavaみたいにStringだけやけに特別だったりしないところが良い。
a = "hogehoge"
b = "foobar"::String
c = ['f','o','o','b','a','r']::[Char]
main = do print $ "hogehoge" == a
print $ b == c
True True
Haskellの「==」は同値かどうかを判定するものなので、イマイチ面白みに欠ける…。のでIntとIntegerだったらどうかというと、
a = 3::Integer b = 4::Int main = print $ a==b
IntEqInteger.hs:3:18:
Couldn't match `Integer' against `Int'
Expected type: Integer
Inferred type: Int
In the second argument of `(==)', namely `b'
In the second argument of `($)', namely `a == b'
怒られる。
■ 基本的な値 - タプル
複数の値を纏めて扱うタプル。タプルいいよな。でもタプルが組み込まれている言語ってPythonくらいしか知らないけど。
ということで、同値性チェック。
a = (3::Int,"hoge")
b = (3, "hoge")
c = (3::Integer, "hoge")
main = do print $ a == b
print $ b == c
print $ c == a
TeqT.hs:6:25:
Couldn't match `Int' against `Integer'
Expected type: (Int, [Char])
Inferred type: (Integer, [Char])
In the second argument of `(==)', namely `c'
In the second argument of `($)', namely `b == c'
あれ?「b == c」でダメか。「c == a」でダメって怒られると予想したんだけど…。タプルに数値リテラルを適用すると、Intになっちゃうってことかな。それとも、先に「a == b」の評価をしたが故にfst bがIntと思われちゃったのかな。
ということで、「a == b」と「b == c」の実行順序を入れ替えてみる。
a = (3::Int,"hoge")
b = (3, "hoge")
c = (3::Integer, "hoge")
main = do print $ b == c
print $ a == b
print $ c == a
TeqT.hs:6:25:
Couldn't match `Int' against `Integer'
Expected type: (Int, [Char])
Inferred type: (Integer, [Char])
In the second argument of `(==)', namely `b'
In the second argument of `($)', namely `a == b'
やっぱり「a == b」で型が違うと怒られる。だから、bの型はIntegerなんだろう。数値リテラルみたいに文脈で型が決まるものは、そうは言えども一度決まっちゃったらずっとその型として扱われるのか。面白いー。
Antionehttp://64fdebd2c057be50b9c19d9a1e08d879-t.xxpogy.org <a href="http://64fdebd2c057be50b9c19d9a1e08d879-h.xxpogy.org">64fdebd2c057be50b9c19d9a1e08d879</a> [url]http://64fdebd2c057be50b9c19d9a1e08d879-b1.xxpogy.org[/url] [url=http://64fdebd2c057be50b9c19d9a1e08d879-b2.xxpogy.org]64fdebd2c057be50b9c19d9a1e08d879[/url] [u]http://64fdebd2c057be50b9c19d9a1e08d879-b3.xxpogy.org[/u] 9dc75301cfe28cfb0fb3d1863c1dee5e
2006-09-14忙しくてもHaskell
2006-09-12Preluedeってステキな名前
■ 4.4 練習問題1
「標準入力を行単位でソート」の意味をどう捉えるのが一般的か。
1. 1行を1要素とみなして、複数行をソート
2. 1行の中に含まれる各文字列を1要素とみなしてソート
日本語の難しさは置いておいて、両方作ってみる。
1. 1行を1要素とみなして、複数行をソート
import List
main = do cs <- getContents
putStr $ unlines $ sort $ lines cs
> sort < sort.hs
putStr $ unlines $ sort $ lines cs
import List
main = do cs <- getContents
空行のみが先頭、スペースから始まるのが2番目、以下アルファベット順。
2. 1行の中に含まれる各文字を1要素とみなしてソート
import List
main = do cs <- getContents
putStr $ unlines $ map sort $ lines cs
> sort2 < sort2.hs
Liimoprstt
-<=Cacdeegimnnnoossttt
$$$Saceeiillmnnnopprrsssstttuu
各行中の要素がソートされております。
で、答えを見たら1.だった。でも$で繋がないで、.で繋いでるのは何でだ…。「=<< getContents」も意味はわかるけど、こんな書き方できるのは知らない。
■ 4.4 練習問題2
import List
main = do cs <- getContents
putStr $ unlines $ map head $ group $ lines cs
text.txt
111 111 222 333 333 2222
>uniq < text.txt 111 222 333 2222
■ 感想
- わかんなくなりそうになったら後ろから順を追って考える
- でもそれって関数型プログラミングなのかな?単に後ろから評価しているに過ぎないような。
- 日本語って難しい
2006-09-10第3章
■ 3.6 練習問題
main = do cs <- getContents
putStr $ concat $ map swapa cs
swapa 'a' = ['A']
swapa 'A' = ['a']
swapa c = [c]
>swapa < swapa.hs mAin = do cs <- getContents putStr $ concAt $ mAp swApA cs swApA 'A' = ['a'] swApA 'a' = ['A'] swApA c = [c]
できたはできたけど、答えをみたらswapaの結果をわざわざリストで返す必要はないらしい。そっか、Char -> Charだから、
map swapa cs
関数適用の結合力がどの中置オペレータよりも結合力が強いので,
print 1:[2,3] は (print 1):[2,3] と解釈されてしまう.
これを防ぐために,print (1:[2,3]) と括弧が必要になる.