ほとんどの日常的なプログラミング作業において、モナドや応用ファンクターなどのHaskellの高度なコンセプトはどれほど重要ですか?


16

Learn You a Haskellの本を読んで、モナドやJust aなどを紹介しています。これらは私にとって非常に直観に反しているので、それを学ぼうとするのをあきらめたいだけです。

しかし、私は本当に試してみたいです。

少なくともしばらくは高度な概念を避けて、言語の他の部分を使い始めて、Haskellのより基本的な部分、つまり関数、標準IO、ファイル処理、データベースのインターフェースなど。

これはHaskellの使用方法を学ぶための合理的なアプローチですか?


2
私はあなたがどこまで到達するかわかりません。モナドなしでは、Haskellで有用なことは何もできません。プログラミングで有用なこと(たとえば、実際に使用したい深刻なプログラムの作成)にはI / Oと状態が必要であり、どちらもHaskellでのみ管理できますモナドの使用を通じて。
メイソンウィーラー

1
@ダン-「君はモナドを発明したかもしれない」と「厄介な部隊に取り組む」という2つの文書を読んで、ようやくHaskellモナドを理解した。私が読んだことのない「Learn You a Haskell」よりも優れているかどうかは言えませんが、彼らは私のために働いてくれました。IOモナドでdo表記を使用するには、モナドが何であるかをほとんど理解することなく取得できます。従来の命令型言語。しかし、さらに深く理解する価値あります。
Steve314

2
@ダン、OOPに飽きて関数型言語に感謝/好奇心を持ち始めるのに10年近くかかりました。Haskellを真剣に試す前に、私はまだF#とClojureを学びました。個人的な挑戦は素晴らしいですが、あなたの腸の感覚と最も抵抗の少ない道について言わなければならないことがあります。多くはあなたが誰であるかに依存します。あなたが非常にマチなタイプの場合、おそらく最初からHaskell / Schemを好むでしょう。あなたがもっと「やる」男なら、それも大丈夫です。Haskellに「do or die」の態度で近づかないでください。他のことを学び続け、退屈したら戻ってきてください。
ジョブ

@Jobのアドバイスをありがとう。Clojureを少し試してみましたが、Lisp構文は、読みと入力の両方で実際には機能しません。Haskellの構文はより自然だと思います。それまではプロジェクトにRubyを使用して満足していますが、Haskellで実用的なプロジェクトをいくつか開始したいと考えています。
ダン

@ダン、面白い、私はClojureの構文がかなりフレンドリーだと思うが、それはおそらく以前にSchemeに触れたことがあるからだろう。多分F#の後、私はHaskellのやり方に慣れるでしょう。
ジョブ

回答:


16

最初に、抽象概念の学習とそれらの特定の例の学習を区別しましょう。

それらが完全に遍在しているという単純な理由のために、すべての特定の例を無視することはあまりありません。実際、抽象化の大部分は、特定の例で実行することを統一するために存在します。

一方、抽象化自体は確かに有用ですが、すぐに必要なわけではありません。抽象化を完全に無視して、さまざまなタイプを直接使用するだけでかなり遠くまで到達できます。最終的にそれらを理解する必要がありますが、後でいつでも戻ってくることができます。実際、それを行うと、戻ったときに額を平手打ちし、なぜ便利な汎用ツールを使用するのではなく、なぜすべての時間を苦労して費やしたのか疑問に思うでしょう。

Maybe a例として取り上げます。これは単なるデータ型です。

data Maybe a = Just a | Nothing

それはすべて自己文書化です。これはオプションの値です。タイプの何かを「ただ」持っているかa、何もありません。ある種のルックアップ関数があるとします。これは、存在しない可能性のMaybe StringあるString値のルックアップを表すために戻ります。したがって、値をパターンマッチして、それがどれであるかを確認します。

case lookupFunc key of
    Just val -> ...
    Nothing  -> ...

それで全部です!

本当に、他に必要なものは何もありません。FunctorsまたはMonadsまたはその他のものはありません。これらはMaybe a値を使用する一般的な方法を表します...しかし、それらはただのイディオム、「デザインパターン」、あなたがそれを呼びたいかもしれません。

あなたが本当にそれを完全に避けることのできない一つの場所はであるがIO、それはとにかく不思議なブラックボックスなので、それが何を意味するのかを理解しようとする価値はないMonad

実際、ここであなたが本当に知る必要があるすべてのチートシートがありますIO

  • 何かにtypeがある場合IO a、それは何かを実行してa値を吐き出す手続きであることを意味します。

  • do表記法を使用したコードブロックがある場合、次のように記述します。

    do -- ...
       inp <- getLine
       -- etc...
    

    ...は、の右側にあるプロシージャ実行<-し、左側の名前に結果を割り当てることを意味します

  • 一方、次のようなものがある場合:

    do -- ...
       let x = [foo, bar]
       -- etc...
    

    ...これは、(式ではなく)プレーン式の値を=、左側の名前の右側に割り当てることを意味します。

  • 次のように、値を割り当てずにそこに何かを置くと:

    do putStrLn "blah blah, fishcakes"
    

    ...プロシージャを実行し、それが返すものをすべて無視することを意味します。いくつかの手順では、タイプしていIO ()--the ()タイプがソートだけで手続きが何かを意味し、値を返さないように、何も言っていないプレースホルダのですが。void他の言語の関数のようなもの。

  • 同じ手順を複数回実行すると、異なる結果が得られる場合があります。それは一種のアイデアです。これがIO、値から「削除」する方法がない理由です。なぜなら、中の何かIOは値ではなく、値を取得するための手順だからです。

  • doブロックの最後の行は、割り当てのない単純なプロシージャである必要があります。そのプロシージャの戻り値は、ブロック全体の戻り値になります。既に割り当てられている値を戻り値に使用する場合、return関数は単純な値を取り、その値を返す操作なしの手順を提供します。

  • それ以外、特別なことは何もありませんIO。これらのプロシージャ自体は実際には単純な値であり、それらを渡したり、さまざまな方法で組み合わせたりすることができます。doどこかで呼ばれたブロックで実行された場合にのみ、main何もしません。

したがって、このまったくつまらない、典型的なプログラム例のようなものでは:

hello = do putStrLn "What's your name?"
           name <- getLine
           let msg = "Hi, " ++ name ++ "!"
           putStrLn msg
           return name

...命令型プログラムのようにそれを読むことができます。という名前のプロシージャを定義していますhello。実行されると、まずプロシージャを実行して、名前を尋ねるメッセージを出力します。次に、入力行を読み取り、結果をname;に割り当てるプロシージャを実行します。次に、名前に式を割り当てmsgます。その後、メッセージを出力します。次に、ブロック全体の結果としてユーザーの名前を返します。ためnameでありString、この手段は、そのhello返す手続きであるString、それは型を持つように、IO String。そして、このプロシージャを実行するように、他の場所でこのプロシージャを実行できますgetLine

Pfff、モナド。誰が必要ですか?


2
@ダン:どういたしまして!途中で特定の質問がある場合は、StackしないでStack Overflowに問い合わせてください。そこにある[haskell]タグは通常かなり活発で、あなたが人々からどこに来ているのかを説明するなら、不可解な答えを投げるだけでなく理解を助けるのにかなり良いです。
CAマッキャン

9

ほとんどの日常的なプログラミング作業において、モナドや応用ファンクターなどのHaskellの高度なコンセプトはどれほど重要ですか?

それらは不可欠です。それらがなければ、Haskellを単なる別の命令型言語として使用するのは非常に簡単です。SimonPeyton Jonesはかつて「世界最高の命令型プログラミング言語」と呼ばれるHaskellでしたが、依然として最良の部分を逃しています。

モナド、モナド変換、モノイド、ファンクター、適用ファンクター、反変ファンクター、矢印、カテゴリーなどが設計パターンです。作成した特定のものをそれらの1つに適合させると、抽象的に記述された膨大な機能を利用することができます。これらのタイプクラスは、単に混乱させるためだけに存在するのではなく、あなたの人生をより簡単にし、生産性を高めるために存在します。私の意見では、これらが良いHaskellコードの簡潔さの最大の理由です。


1
+1:「モナド、モナド変換、モノイド、ファンクター、適用ファンクター、反変ファンクター、矢印、カテゴリーなどは設計パターンである」と指摘してくれてありがとう。!
ジョルジオ

7

何かを実行したいだけなら絶対に必要ですか?番号。

美しい慣用的なHaskellプログラムを書きたい場合は必要ですか?絶対に。

Haskellでプログラミングする場合、次の2つのことを念頭に置くと役立ちます。

  1. 型システムはあなたを助けるためにあります。非常に多態的なtypeclass-heavyコードからプログラムを作成すると、たいていの場合、必要な関数のタイプが(1つの!)正しい実装に導かれるという素晴らしい状況に陥ります

  2. 利用可能なさまざまなライブラリは、原則#1を使用して開発されました。

そのため、Haskellでプログラムを作成するときは、型を作成することから始めます。次に、最初からやり直して、より一般的な型を書き留めます(既存の型クラスのインスタンスにできる場合は、それでもなお良いです)。次に、必要な型の値を取得する関数をいくつか作成します。(それから私はそれらで遊んでghci、おそらくいくつかのquickCheckテストを書きます。)そして最後にすべてを一緒に接着しmainます。

何かを実行するだけのいHaskellを書くことは可能です。しかし、その段階に到達したら、学ぶべきことがたくさんあります。

幸運を!


1
ありがとうございました!私はClojureとHaskellの間で揺れ動いてきましたが、今では私はHaskellに傾いています。
ダン

1
Haskellコミュニティはとても親切で役立つようです。そして、それは多くの興味深いアイデアがどこから来たようです
ザカリーK
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.