カテゴリー: Haskell

Home / カテゴリー: Haskell

主語が違うのか?

2013-03-03 | Haskell | コメントはまだありません

SCV?CSV?なんか英語の時間にそういうのがありました。VSOP?
あたしは駅の階段をゾンビみたいに歩きながらふと思いました。
「関数型言語というくらいなんだから関数を主語に考えないと駄目なんじゃないの?」
ようこそ。ここはHaskell理解に苦しんでいるおねーさんの姿をご笑覧いただくブログです。

そういった理解の方法で合っていたかは知りませんが、たとえば

def foo(a, b):
    return a + b

foo(2, 3)

のようなケースにおいて、あたしの主語は「値」でした。2と3を渡して、箱の中でなんかして、結果(上のfooさんの場合だと)5が返ってくる。
2と3をあれして5を取り出すモノが関数だったわけです。あたしにとって。
が、Haskellのお勉強をしていると、次から次へと「関数が返ります」「関数を適用します」のオンパレード。値がどうかといった話はあんまり出てこない。
あたしにとって主語だった「値」不在で、関数という「何かするハコ」の話ばかりだから、あたしはどこに目線を置けばいいのか分からなくなって、そんで混乱しているのではないか。
おお。
なにも解決はしてないが、少し視界がクリアになった感。

お恥ずかしい話ながら

♪ 地球はひとつ 割れたらふたつ

の世界観で生きております。お~ガッチャマーンです。リンゴ切って二個です。0.5個とか言わねえだろうが!って怒るタイプです。一言でいうと算数の初期にすっ転んでいます。
aとbを渡してcを返すもの、とかいう抽象的な話を理解するのが苦手なのかもしれません。おかしいな、二次連立方程式とか因数分解とか、(もう覚えてないけど)あの頃は好きだったのになあ。あれは勘違いだったのかなあ。

ともあれ、ウンウンいってしばらく苦しむのがいいんです。脳の筋トレになると思えば安いものだ。中学生高校生の頃にサボったバチだ、ざまあみろ。
はーつらい。
さしあたり、主語は関数であると唱えながら本を読んでみようと思った次第。

すべて関数です

2013-03-02 | Haskell | コメントはまだありません

えーと。
すごいHaskellの61ページから「高階関数」というものの説明が始まっています。

Prelude> :t max
max :: Ord a => a -> a -> a

(本にある記述ではないです。あたしの手元のghciさんに吐かせた中身)
で、これを本では、次のようにも書けますという。

max :: (Ord a) => a -> (a -> a)

はい。はい?

矢印->を型シグネチャに含むものはすべて関数です
(すごいHaskellのp.62)

a->bの「a->」と「->b」と、どっちに捉えたらいいのやら?
最後(右端)にあるのは返り値であるということからすると、「a->」って考えればいいのかな。
a+b+cを返すみたいなのを書いてみる

Prelude> let foo x y z = x + y + z
Prelude> foo 9 10 11
30

型をみてみる

Prelude> :t foo
foo :: Num a => a -> a -> a -> a

このばあいのー、まずいろんな成分を分けないといけない。あたしが読解する用に。

Prelude> :t foo
foo :: (Num a) => a -> a -> a -> a

「Num a」を括弧でくくって、視線から離す。残った問題の「a -> a -> a -> a」を考える。

矢印->を型シグネチャに含むものはすべて関数です

関数に渡すものは変数であると覚えたあたしの脳が、この1行を飲み込むのを拒絶する。厳しい。

a -> a -> a
↑おなじ↓
a -> (a -> a)

は、aの型を引数に取りa->aを返す関数と読むことができると書いてある。

a -> a -> a -> a
↓
a -> (a -> a -> a)
↓
a -> (a -> (a -> a))

みたいな?みたいなと書いてはいますがぜんぜん飲み込めない。いまはまだ、あたしの脳の外周を水カビみたいに浮いてる考え方だ。知恵でなく知識。
aばっかりで全然分からぬ。

x -> y -> z -> v
↓
x -> (y -> z -> v)
↓
x -> (y -> (z -> v))

書き換えてみる。
xを引数で渡して、「y -> (z -> v)」って関数を返す。
その「y -> (z -> v)」は、「z -> v」って関数を返す。
値vが返る。
この無限にタマネギを剥くような感覚。

関数の部分適用という考え方があった。

Prelude> (+) 3 4
7
Prelude> (+) 3
:1:1:
    No instance for (Show (a0 ->
      arising from a use of `prin
    Possible fix: add an instance
    In a stmt of an interactive G
Prelude> ((+) 3) 4
7

ここはなんとなーく分かるようになってきたが、染み込んでない。
型シグネチャっていうの?抽象的な表記をされたとたん、あたしの脳が「これは難しいものだ危険!」みたいになって、受取拒否をしているかのようですよ。
どっかでとつぜん染み込んだりするようになったりするものなので、しばらくはこの負荷をかけ続ける所存でございます。はやくこいブレークスルー。

身についてないっぽいポイント

2013-03-01 | Haskell | 1件のコメント

Haskellです。
Pythonがどんだけ読みやすく書きやすい言語であったか痛感してます。
はーん。

(+)

+とかでなくてもいいんだけど、カッコで括られてる箇所を関数と読取り慣れていない。

(\x y -> x + y)

これが何してんのかすぐに読めない。
どうも関数\xと引数yって読んでしまい、思考が脱輪するのね。

Prelude> :t ($)
($) :: (a -> b) -> a -> b

こういうのを、(a->b)は関数で、引数がaで、bがreturnされる、と読めない。
a -> (a -> b) -> bって書いてくれればいいのに。
「(a->b)って関数」をaに適用します、結果がbですと読むんだろうけれども、まだまだ脳味噌が追いついてくれない。
あー書いててわかってきた。あたし主語として捉える対象を間違ってんだ?そうなこれ?
ホニャララってデータを関数ウンタラで云々してこうなります、ではなく、ウンタラって関数をホニャララに適用して云々、そう読めってことか?

関数型言語の関数を視認できてない。そりゃー読めないわなあ。

表現の種類

2013-02-28 | Haskell | コメントはまだありません

おねーさんです。
今日も昨日も行き帰りの電車の中では”すごいHaskell”を読み、速やかに昏睡状態へと移行する動作を続けております。Haskellはすごい。

ここ数日で最もいらいらするのは畳み込みです。
foldl。そうか。foldl1。ちょっとちがう内容だから数字つけたのね。そうか。いや、これは看過できぬ。
きっと深淵で無駄のない洗練された理由があるんだとは思いますけど、いまのあたしはこう思う。
「ほんとに頭の良い人が作ったの?センス悪くない?あまりにも場当たり過ぎじゃない?」
こういうところでガックリきて、はーまじかーなえるわーってなって寝るんだわ。
#foldlというのは左畳込みとかいう処理をする関数さんであるらしいです。なるほどわからん。

tnomura9さんの「tnomuraのブログ」というサイトをこないだ見つけて、たまに読んでいます。
Haskell 記事リスト」というカテゴリがまとめられていて、まだ最初の方だけしか読めてないけれど、書き口がわかりやすくて読みやすい。
すごいHaskellとともにこのサイトを副読本として読んでいこうと思います。ありがたいなあ、こういう記事を置いてくれる人がいて。

いろんな表現があるのだな

その、tnomura9さんのページに例題が出ているので、それをちょいちょいやってみる。

「1から10までの数の2倍の数のリストを出す」

あたし:
Prelude> [x*2 | x <-  [1..10]]

リスト内包表記だ。Pythonで覚えたんだワイルドだろう。

上記のページ:
Prelude> map (* 2) [1..10]

オ-ゥ。
もうここで違う。結果は同じよ?同じなんだけど、map関数を使うこと、「(*2)って関数」を与えること、このへんの発想があたしに欠落しているということがよくわかる。
はーなるほど。次。

「1から10までの数の平方数はどうだろうか。」
次の行を読まずにまず自分で書く。わかってんだよmapだろmap。

あたし:
Prelude> map (^2) [1..10]

で、

上記のページ:
Prelude> map (\n -> n * n) [1..10]

む、むめいかんすう。。。
むろんやってることは同じではございますが、そういう表現もあることを知った上で、どっちの書き方を選択するか、といったふうにしておきたいものです。

Prelude> :t \n -> n*n
\n -> n*n :: Num a => a -> a
Prelude> :t (^2)
(^2) :: Num a => a -> a

Python覚えたての頃、何をやってたかを書き残しておけばよかったなあ。言語ってどうやって覚えるんだっけなー。

ドットつなぎ記法

2013-02-26 | Haskell | コメントはまだありません

あたくしにとってドット(.)というのは、文字列結合を指すものにほかなりませんでした。後にいろんな世界で色んな意味をもつ記号であることを知るにいたり、言語ごとの思想の違いであるとかに目がクラクラした次第であり、し続けている次第であります。
ほんでHaskell。
ドットつなぎは、関数合成です(キリ
あー、そっすか。関数の、合成っすか。失敗すると外道スライムが沸いたりするっすか?

すごいHaskellのp99。

import Data.Char
import Data.List

digitSum :: Int -> Int
digitSum = sum . map digitToInt . show

数字列を受け取り文字列に変換して、各文字(数字)の合計をするというサンプル。本にある例文です。
1234と入れたら、1+2+3+4で10を返すと。
で、これがまたわからない。ドットが関数合成なるものであることは見ました本で。
で、これ、えーと、引数どこいった。
これはえーと、あまりにも引数が自明なあまり省略しましたみたいな話ですか?
で、色々こねくり回していると、どうも、

digitSum 1234

は、

(sum (map digitToInt (show 1234)))

と等しいようだということがわかりました。

  1. showは受け取った値を文字列にする、
    1234→”1234”
  2. digitToIntは文字0-fを数値にする、
    “1”→1
  3. mapはdigitToIntを各桁に対して行う、
    [“1″,”2″,”3″,”4”]→[1,2,3,4]
  4. sumで合計する
    1+2+3+4

とすると、

digitSum = sum . map digitToInt . show

の右端から順に読んでいくと同じことになるわけだー?
なんで右から読むのと左から読むのとあるんだ。読む向きがわかんなくて目がチカチカする。。。
リスト内包表記もPythonさん経由で慣れてるというのは大きいにしろ、やはり視線が左右に泳ぐ傾向があり、さくっとわかりやすく、左から右へ、流れるように読みたいものだと思う昨今です。
どちらを先に学んだかでしかないんだろうけど、

Haskell:
sum . map digitToInt . show

これと、

jQueryなど:
uu().yaa().taa()

みたいなのがこう、頭のなかで混ざってですね、マーブル模様になるんすよ。
関数の合成とメソッドチェーンとは違うものか?きっと違うな?少なくとも読む方向は逆だな?
そんなかんじでモヤモヤしております。
違う思想、哲学、体系を学ぶというのは、ほんとうに大変なことだなあ。

このままじゃ脳が外道スライムになるっすよー。