Haskellの型というかデータコンストラクタ

構成子関数は評価済みであり、それ以上簡約できないとはどういうことなんだろうか?

data MyAdd = MyAdd {ev :: (Int -> Int)}

これはIntをとってIntを返す関数を表す型

*Main> let add5 = MyAdd (\n -> n + 5)
*Main> :t add5
add5 :: MyAdd

MyAdd型ってなっててこれ以上簡約できない。でも実態はラムダ式なんでしょってことで、Intを渡すとエラー

*Main>add5 3

<interactive>:1:0:
    Couldn't match expected type `t1 -> t'
           against inferred type `MyAdd'
    In the expression: add5 3   
    In the definition of `it': it = add5 3

evアクセサをつかってアクセスする。

*Main> ev add5 3
8

要するに型とは簡約のレベル(深さ)を定義するってこと?

追記 091217

構成子関数はこういう型だと認識して納得。その後TLを追いかけ直して、理解した。

MyAdd :: (Int -> Int) -> MyAdd

確かに、いろいろ入り混じって混同してました

よくよく考えてみるに、僕はこの右辺を(Int -> Int)という(ラムダ関数みたいなもの)にMyAddっていうラベルをつけるみたいなイメージを漠然と持っていたようです。

data MyAdd = MyAdd (Int -> Int)

で、

let add5 = MyAdd (\n -> n + 5)

とやると(MyAdd型にラベル付けされた)関数に束縛されたadd5っていう変数が生まれると。 だから型で一時停止してその先には(\n -> n + 5)っていう関数が待っているのかなぁつまり、

型とは簡約のレベル(深さ)を定義するってこと?

という、冒頭のような勘違いをしていた。

型とは新規な器みたいなものだと捉えられるようになったら、下の話も理解できた。

mzp

@kzfm うーん、うまく説明できないんですが、そもそも単なる別名になってほしくないからnewtypeを使っていて、別名になってほしいならtypeを使うと思うんです。だから、Parse型の値に引数を適用できないのは、そのほうが型チェックの恩恵を受けれるからだと思います。

koyama41

@kzfm newtypeは結果的に一個の型に別名をつけるだけに見えてしまうのでtype文に似てるように思ってしまうのですが、むしろdata文の特殊な形と思った方がいいと思います

ProductName プログラミングHaskell
Graham Hutton
オーム社 / ¥ 2,940 ()
在庫あり。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan,John Goerzen,Don Stewart
オライリージャパン / ¥ 3,990 ()
在庫あり。

リストってもんがちょっと分かった気がする

SICPの2.2.1章の「並びの表現」っていうところを読んで、carとかcdrのでリストを表現の仕方を学んだ。

これ読んでhaskellのアレが理解できた。アレってばhaskellの:演算子のこと。

[1,2,3]
= 1 : [2,3]
= 1 : 2 : [3]
= 1 : 2 : 3 : []

最初普通のhaskellプログラミングを読んだときにはよくわからなかったけど、carとcdrが理解できた今ならこれって凄く自然に思えてくるのが不思議。

ProductName ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
青木 峰郎
ソフトバンククリエイティブ / ¥ 2,940 ()
在庫あり。

それにしても、SICPおもしろいなぁ。なかなか進まないけど。

リストの覚書き

お盆なんでU隊長の実家にいったんやけど、やることないのでSICP読みながら遊び中。

haskellの

[1,2,3]
= 1 : [2,3]
= 1 : 2 : [3]
= 1 : 2 : 3 : []

は、gaucheで

(list 1 2 3)
= (cons 1 (list 2 3))
= (cons 1 (cons 2 (list 3)))
= (cons 1 (cons 2 (cons 3 '())))

カッコがないほうがわかりやすいナァ(ボソッと)。

モナド(副作用の意思を伝える?)

非決定性計算とかambでどんづまり。なんか色々みているうちにうっかりモナドに迷い込んでしまった。

世界で一番か二番くらいにやさしい「モナド入門」

我々の課題を思い出してください:「副作用付き計算を、純関数で表現せよ」でした。カウンター(大域変数count)に触ることは副作用ですから、これをやめましょう。んじゃ、カウントアップできないじゃないか! って?はい、そのとおり。でも、「カウントアップしたい」という意志を伝えることはできます。

Perlの駱駝のこぶにはMonadも入ってる

結局Monadを実装するためには、値と副作用を別々に保持し、値に関しては参照等価性を保ちさえすればいい。

    $op0->{value} = eval{
        $coderef->($op0->{value}, $op1->{value});
    };
    if ($@){
        $op0->{state} = $@;
        $op0->{value} = undef;
    }

evalで「失敗するかもしれない演算」を包んで「より大きな失敗するかもしれない演算」を作るって解釈すればよいのかな。

ProductName ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
青木 峰郎
ソフトバンククリエイティブ / ¥ 2,940 ()
在庫あり。

あとでふつうのHaskellプログラミング読み返そう。

Haskellすごいなぁ

現実逃避もかねて、どう書く?解いてた。

Higher-order Perlのおかげでこんな感じの問題は、まず再帰で考えることができるようになった気がする。

ProductName Higher-Order Perl: Transforming Programs with Programs
Mark Jason Dominus
Morgan Kaufmann / 5692円 ( 2005-03-28 )


それにしても、haskellの二行ってすごいなぁと思った。

モナドは世界観と枠組みなのか

今日は半日以上モナドに関するネット上の文章をあさっていたうえに、考えすぎ疲れで昼寝もした。

そのせいか少し前進した。特に参考になったところをメモ。

HaskellのモナドIO

さて,f が入出力を行う手続だとしたら f を引数に適用したときの値は,引数の値だけではなく,その時のプログラムの外側の世界に依存することになります.また,入出力を「実行」した後の世界は,「実行」前の世界とは別の世界になっているでしょう.この様子を Haskell のプログラムで表現すると(つまり世界の更に外側から見ると)

サルでもわかるIOモナド①-副作用の除去

具体的に言いましょう。上で示した関数(y, world')= f(x, world) において x を与えてやると(あるいは、束縛すると)、 (y,world') = g(world)という新しい関数が出来ます(このように関数の引数の一部を束縛することによって新しい関数を作ることを、カリー化というそうです)。この関数 g を、アクションの実装とすることができます。 putStrLn を例にとりましょう。この関数のもとの形(カリー化前の形)は:

putStrLnOriginal:: String -> World -> ( (), World )

と考えることができます。これをカリー化すると:

putStrLnCurried:: String -> ( World -> ( (), World) )

となります。この関数の返り値の型が、上述した g と同じになっていることにご留意ください。これをアクションすなわちIO()に置き換えたのが:

putStrLn:: String -> IO ()

見慣れた形ですね。

なぜモナドを理解しようとするのか

プログラマにとってモナドは関数プログラムの構造化に有用なツールです。モナドには、それを特に有用なものとしている 3 つの性質があります。

  1. モジュラリティ - より単純な計算から計算を合成することができ、実際に 実行される計算と合成戦略を切離すことができます。
  2. 柔軟性 - 関数プログラムをモナドなしで書いた同等のプログラムよりも はるかに柔軟なものとすることができます。これはモナドが、計算戦略を プログラム全体にばら撒くことをせずに、一箇所に引出すからである。
  3. 分離性 - 関数プログラムの本体から安全に分離したままで、命令スタイル の計算構造を生成するのに利用できます。これは、Haskell のような純粋 な関数型言語と入出力のような(参照透明性を破壊するような)副作用と組 み合わせるのに役立ちます。

でもって、内部状態を持たないことで云々というくだりはRESTfulウェブサービスでみた内容に似ているなあ。モナドとRESTfulはなんか関係あるのかなと思いググってみたら、こんなのを見つけた。

haskellをスクリプト言語っぽく

runghcを使わないとコンパイルしなくてもいいらしいので

#!/usr/bin/runghc

import System

main = do cs <- getArgs
          print cs

といった感じで使える。

でも、遅いのであまり役にたたなさげ。

あと、今週末はふつけるの1,2部を読み直してみて、型まわり(9章)をよく読んだ。

ProductName ふつうのHaskellプログラミング ふつうのプログラマのための関数型言語入門
青木 峰郎
ソフトバンククリエイティブ / ¥ 2,940 ()
在庫あり。

あとlengthは要素を評価しないとかいうくだりを読んでデータコンストラクタとか型コンストラクタって関数みたいだとか思ったら、まぁそんな認識でよいらしい。

3.4 「無限の」データ構造

Haskell の非正格な性質の利点のひとつは、データコンストラクタもが非正格であることです。このことはべつに驚くべきことではありません。コンストラクタは特殊な関数にすぎません(ふつうの関数との違いは、パターンマッチで使われるということです)。たとえば、リストの構築子、: は非正格です。

Type (の最後のほう)

静的型という制約を、抽象化のための思考の道具として使う

やさしい Haskell 入門 (バージョン98)をじっくり読んでみよう。

MeadowでHaskell

最近のhaskell-modeはhaskell-site-fileをロードするだけでよいらしい。.emacsに書いておいた。

(load "c:/Meadow/site-lisp/haskell-mode-2.4/haskell-site-file.el")

これで、C-cC-lでghciが起動してファイルをロードしてくれるので楽だ。 今はHaskellプログラミングを読んだり解いたりしてる。ちなみに和田先生のルービックキューブのやつとか難しくてわからんのでスキップしたが、その次のメモ化の章はやたらとおもしろい(まだ消化してないけど)

type State s t = s -> (t,s)

とかやって関数の型を抽象化してるんだけど、いまいちついていけない自分の理解力がもどかしい。

入門Haskell買った

昨日TOEICがあったので先週はiKnowばっかやってた。TOEICの出来は微妙なとこだけど、ちょっとiKnowの効果は出たみたい。ディクテーションよいですな。あと単語力上げるのにもいいが、やっぱdiaryをつけねばならんね。

で、合間に本物のプログラマはHaskellを使うとかHaskellプログラミング読んだりとか。っつーかこっちのほうが難しすぎ。2005-8のメモ化の話で何日か考え込んでた。

さて、英語もひと段落したので年始からはまりっぱなしのHaskellでもと、入門Haskellを購入して読むことにした。

ProductName 入門Haskell―はじめて学ぶ関数型言語
向井 淳
毎日コミュニケーションズ / ¥ 2,730 ()


一気に4章まで読んだ。明日は通院なので待ち時間に5章のモナドのとこ読みつつ、サメガメ作り(6章)をやる予定。

少しいろいろやってみてからこの本を読むと面白さが伝わってきてよい。解説のとことか、ほーなるほど、あーそうなんだと思うようなことが多かった。ふつけるはHaskellを知ろうっていう構成なのに対して入門HaskellはHaskellで書こうって感じの本だなぁという印象。

で、Haskellでもっと書こうって思ったときにこの先何を読めばよいのかわからんなーってのがHaskellの悩みどころですな。

とかやってみて、

  • ParsecでPDBパーサーを書いてみる
  • HappSいじってみる

とかかなぁ。perlとかpythonは探せば(上達の)階段らしきものは得られるのに、Haskellだと、いきなり20階ぐらい上にエレベーターで飛ばされる気分なんだよな。この間を埋めるいい書籍とかWebの情報はないのかなー。

wxHaskell入れた

入門Haskellの6章はsamegameをつくろうの章だ。

haskellの標準GUIのHGLで簡単なサンプルでもと動かそうとしたら、動かん。どうもWindowsでは標準から外されたらしい。

あらーん、ということで、じゃぁwxHaskellでもと思ったが、こっちもなんか開発とまってんの?って感じで最新のHaskellには対応してなさげ。コンパイルすればいいのかねー。うーん。

と悩んでいたら、6.8.1だったらOKらしい。おーありがたいと早速入れた。

で、入門Haskellのサイトのwxsamegameを動かしてみた。

samegame

ちゃんと動いてるよ!。ちょっとうれしい。