Just!!

Filed in Haskell Leave a comment

あいかわらず、すごいHaskellを読んで寝ています。
家に帰るとヨメとゲームやっちゃうし仕事中にHaskell遊びするわけにもいかんしで、本読んでばかりで手を動かしていません。だから実感なくて寝るんじゃないかバカなの。

いまだにHaskellの構文を見てピンとくるシーンが少ないです。あたしの脳がHaskellの文をパターンマッチングできてないんだわ。x:xsを認識するのがあたしの限界か?

今日はJustで遊んでみます。
Maybe a型という、なんかもういきなり「ハァ?」と思わずにいられないネーミングのそれですが、

*Main> :t Just 1
Just 1 :: Num a => Maybe a

*Main> :t Just 'A'
Just 'A' :: Maybe Char

*Main> :t Just "Abc"
Just "Abc" :: Maybe [Char]

*Main> :t Just []
Just [] :: Maybe [a]

*Main> :t Just [1]
Just [1] :: Num t => Maybe [t]

いたずらを思いついた。

*Main> :t Just Nothing
Just Nothing :: Maybe (Maybe a)

ほー。
こんだけかと言われそうですが、何かと勝手に制約を課しがちな、固いあたしの脳みそにとってはわりと快挙というか金星というか、ほめてあげたい感じ。えらいぞあたしの脳。

*Main> :t Just Just 1
:1:1:
    The function `Just' is applied to two arguments,
    but its type `a0 -> Maybe a0' has only one
    In the expression: Just Just 1

ダメだろうなとは思ったんだけど。

*Main> :t Just $  Just 1
Just $  Just 1 :: Num a => Maybe (Maybe a)

こうですね。

わからんとこだらけだけど読み進めよう、と思って読み進めると、次々にわからんことになって後戻り。
学ぶと難しいが使えば簡単、といったことをtnomura9さんも仰っていたので、まあまずは黙って手を動かせよってことですよね。

Haskellのクラスはちがう

Filed in Haskell Leave a comment

本の何処かに「Haskellのクラスは、JavaやPythonのクラスとは違う概念だから!Pythonとかのクラスのことはきれいに忘れてほしいな!」とか書いてある。
違う概念なんだったら違う言葉で表現していてほしい。Haskellのver1.0が世に出たのは1990年だというから、そのころならまだ、クラスを別の呼び方にするには間に合ったんじゃないのか。なんなのか。
いまだに用語のアレコレが染み付いておらず、電車の中で読むたびに寝ています。
という愚痴。

いつか学習しているうちにたどり着いて見つけるのかもしれないが、とあるオブジェクトのかたちと振舞いを定義した塊としてのクラス、Pythonやphpで言うところのクラスのような定義の仕方についての記述がなかなか出てこないことが、不安として横たわっています。
既知の「クラス」をモジュールとかのあたりのファイルを単位とした何かで担うのであろうか。
いちいち置き換えて考えようとするのは悪手なんだろうとは思うんだけど、漠然とわからないまま彷徨うあまり、手がかりを探してしまう感じ。

データ型を定義するの辺り

Filed in Haskell Leave a comment

すごkellp112の「形づくる」のあたり。
#ページ進んだとおもいきや戻ってという読み方をしているので一向に進みません。

テキスト読みながらぼんやり書いてぼんやり動かして、数日うまくいかないことがありました。
さっき解決したのでメモ。

円と矩形の定義をして、面積を得る関数を書きましょうみたいなあたり。

data Shape = Circle Float Float Float |
             Square Float Float Float Float 
     deriving (Show, Read)

area (Circle _ _ r  ) = pi * r ^ 2
area (Square _ _ w h) = w * h

piは予約語なんだな。
こう書いて、

*Main> area $ Circle 10 10 10
314.15927

うん。

*Main> area $ Square 10 10 10 10
*** Exception: shape.hs:5:1-39: Non-exhaustive patterns in function area

えー。
dataの宣言のところの改行が良くないのだろうかとか、インデントの位置だろうかとか、そらもういろいろ試したがここから数日間動けず、イライラしておりました。
Circleの面積は得られる。
Squareは得られない。Squareが予約語なのかも!とかで書き換えてみてもダメで、ああそうだ、なんか型の宣言を書いといたほうがいいみたいな話だったなあと思い、

data Shape = Circle Float Float Float |
             Square Float Float Float Float 
     deriving (Show, Read)

area :: Shape -> Float
area (Circle _ _ r  ) = pi * r ^ 2
area (Square _ _ w h) = w * h

1行書き足し。
これがじつは正解で、

*Main> area $ Square 10 10 10 10
100.0

うごいた。
本には「型宣言を書いておくことはよい習慣です」くらいの書き方してたけど、違うじゃん。
必須じゃん。

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

Filed in Haskell Leave a comment

先日の記事で、

(\x y -> x + y)

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

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

こういうのを、(a->b)は関数で、引数がaで、bがreturnされる、と読めない。
a -> (a -> b) -> bって書いてくれればいいのに。

と書いた。

a -> (a -> b) -> bって書いてくれればいいのに。

これ中置き関数じゃないか。a `mod` bじゃないか。
で、a `mod` bはもともとは(mod) a bなんだから、結局

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

の形に戻ってくるんだわな。
自分の視覚にとっての読みやすさの問題なんだなー純粋に。

中国の剰余定理

Filed in Haskell Leave a comment

逆ポーランド記法の電卓があるらしいと知り、hpの10,000円くらいの高機能電卓、それもなぜかグラフ表示までできるようなやつをみてびっくり、amazonのレビューも筋金入りの数学オジサマがたの巣窟となっている感があり、いやはや世の中にはいろんな世界があるものだと逃げ帰ってきた次第です。
で、hp 50g ハイエンド グラフ電卓という電卓のレビューで、

しかしながら2300を超えるといわれる関数には、整数a, b, cを与えてau + bv = cを満たす整数u, vを計算するIACUVという関数や、中国の剰余定理の解を求めるICHINREMやCHINREMなど数学の専門家でもなければなかなかお目にかかることのないものまで含まれています。

この電卓にはいっぱい関数が入ってるらしい。
そ、そうですか。
言われてみれば普通の√とかもあれ、関数か。どころか、加減乗除ぜんぶ関数だ。それのもっといろんなことができるのが関数電卓だということなんだな。
あたしがこの電卓を買っても全然アレなので買うつもりはないけど、
中国の余剰定理
という一文に目が止まりました。なにこれ。なんだかマイナーな関数の搭載がされているという話ですが、そういう定理があるのね。
んでWikipediaの「中国の剰余定理」を見てみる事にしました。

『孫子算経』には、「3で割ると2余り、5で割ると3余り、7で割ると2余る数は何か」という問題とその解法が書かれている。中国の剰余定理は、この問題を他の整数についても適用できるように一般化したものである。

あら、シンプルな話。これならあたしにも何とかできそう。
#孫子算経というのは中国の古い書物で、数学や暗号について書かれたものだそうです。

解いてみる

三種類の数で割った剰余がそれぞれtrueだったらナンチャラ、というのを書けばいいんだろう。
[1..]とかで順番に洗っていけばいいんだわな。
[1..]だと終わりがないからいかんな。さしあたり[1..100]とかにしとこう。見つからなかったら1000とか10000とか数字を上げていけばよろしい。
#ちなみに、うっかり見ちゃったので、上の条件を満たすのは最小で23だということまでは把握しています。ちぇ。

こんなかんじ?

Prelude> let foo x = (x `mod` 3 == 2, x `mod` 5 == 3,x `mod` 7 ==2 )

さっそくためします。

Prelude> foo 23
(True,True,True)
Prelude> foo 22
(False,False,False)
Prelude> foo 8
(True,True,False)

うん。んー、うん。

Prelude> :t foo
foo :: Integral a => a -> (Bool, Bool, Bool)

タプルで返ってくるのは不便だ。ぜんぶ満たしてたらTrueでいいんだけど。

Prelude> let foo x = (x `mod` 3 == 2 && x `mod` 5 == 3 && x `mod` 7 ==2 )
Prelude> :t foo
foo :: Integral a => a -> Bool

どうかな。

Prelude> foo 23
True
Prelude> foo 22
False
Prelude> foo 8
False

書き方あってたみたい。で、リストの中から条件に合うものを拾うのはfilterだということなので、

Prelude> :t filter
filter :: (a -> Bool) -> [a] -> [a]

Boolが返る関数とリストを渡すのね。

Prelude> filter foo [1..100]
[23]

お。

Prelude> filter foo [1..1000]
[23,128,233,338,443,548,653,758,863,968]

おお。
実に大したことはないんですが、嬉しい。
少なくともいまのうちは、htmlだcgiだバッチだと吠えるよりは、こういう算数あそびに使ってるほうがいいのかも。

そーいえば

takeで先頭n個の取得ができるんだった。

Prelude> take 1 filter foo [1..1000]

:1:1:
    The function `take' is applied to four arguments,
    but its type `Int -> [a0] -> [a0]' has only two
    In the expression: take 1 filter foo [1 .. 1000]
    In an equation for `it': it = take 1 filter foo [1 .. 1000]

あちゃー。
そうか、このままだと take 1 で拾おうとするリストが”filter”になっちゃうんだ。
$つけよう。

Prelude> take 1 $ filter foo [1..1000]
[23]
Prelude> take 1 $ filter foo [1..]
[23]

これなら[1..1000]じゃなくて、[1..]でいいんだな。Lazyはよい。
少し賢くなった気分。

主語が違うのか?

Filed in Haskell Leave a comment

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を返すもの、とかいう抽象的な話を理解するのが苦手なのかもしれません。おかしいな、二次連立方程式とか因数分解とか、(もう覚えてないけど)あの頃は好きだったのになあ。あれは勘違いだったのかなあ。

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

すべて関数です

Filed in Haskell Leave a comment

えーと。
すごい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

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

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

Filed in Haskell 1 Comment

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ですと読むんだろうけれども、まだまだ脳味噌が追いついてくれない。
あー書いててわかってきた。あたし主語として捉える対象を間違ってんだ?そうなこれ?
ホニャララってデータを関数ウンタラで云々してこうなります、ではなく、ウンタラって関数をホニャララに適用して云々、そう読めってことか?

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

表現の種類

Filed in Haskell Leave a comment

おねーさんです。
今日も昨日も行き帰りの電車の中では”すごい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覚えたての頃、何をやってたかを書き残しておけばよかったなあ。言語ってどうやって覚えるんだっけなー。

ドットつなぎ記法

Filed in Haskell Leave a comment

あたくしにとってドット(.)というのは、文字列結合を指すものにほかなりませんでした。後にいろんな世界で色んな意味をもつ記号であることを知るにいたり、言語ごとの思想の違いであるとかに目がクラクラした次第であり、し続けている次第であります。
ほんで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()

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

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

TOP