本気でHaskellに入門したかったので「Get Programming with Haskell」を読んだ

久々の投稿です。

今回は、最近読んだこちらの本がHaskellの入門書としてとても良かったので紹介したいと思います。

www.manning.com

こちらの本は、ManningAmazon で購入することもできますが、サブスクリプション型の O'Reilly Learning (Safari Books Online) でも読むことができます。(ちなみに私はSafariで読みました)

はじめに

私のこれまでのHaskellとの関わりは、数年前に「すごい Haskellたのしく学ぼう! 」(通称: すごいH本)を読んだことがある程度で、その時はHaskellを学ぶことよりも、Monadについての知識を深めることが目的でした。

しかし月日が経過し、心境の変化というか、最近何だか無性に体がHaskellを求め始めてきたので、これを機にちゃんと入門することにしました。

入門するにあたり、すごいH本をもう一度読んでも良かったのですが、どうせなら新しめな本でかつ実践的な内容が書かれている入門書を探していたところ、この本にたどり着いたのです。

この本を読んで得られること

この本は、Haskellの基本が体系的にまとまっていて、しかも文章の構成がとてもうまいので、順番に読み進めていくことでHaskellの以下の知識が身に付くようになっています。

  • 関数型プログラミングの基礎
  • Haskellの基本構文や型、再帰処理
  • 再帰的なデータ構造
  • 代数的データ型(algebraic data type)と各種型クラス(type class)の性質と実装方法
  • IOで不純(impure)な世界の扱い方
  • Haskellの文字列型(String、Text、ByteString)の扱い方
  • GHC拡張
  • Stack(ビルドツール)の利用方法
  • QuickCheckを使用したProperty-based testing
  • JSONエンコード・デコード、DBアクセス、HTTPリクエスト などなど

それと最後まで読んで感じたのが、コードの書き方で、いくつか方法がある場合でも学ぶ人が混乱しないように何種類かに限定し、それを本全体を通して一貫性を持たせていることです。例えば、Haskellにはパターンマッチのやり方が色々あると思いますが、敢えて網羅的ではなく何種類かに絞ったやり方で解説しています。

それ以外にも、let ... in よりも where を、 newtype は紹介こそされていますが、本全体を通してサンプルコードには登場していなかったと思います。また、Monadは、Maybe、List、Either、IOは書かれていますが、Reader、Writer、State等は書かれていないことや、Monad Transformer、Lens、それから並行・並列処理についても書かれていません。

この辺は賛否両論あると思いますが、個人的には、何かの言語を学ぶのに1冊しか読まないということはまず無いと思うので、入門書としてこれはこれで良いのかなと思っています。網羅的に学ぶのであれば、他の本も併せて読んだ方が良さそうです。

見せ方がうまいなと思ったところ

この本は大きく7つのUnitで分かれており、最初の Unit 1 は関数型プログラミングの歴史や利点、Haskellの基本を解説しています。ただし、この時点では型のことは一切触れていないので、まるで動的型付け言語であるかのような見せ方をしています。しかしそれが Unit 2 へ進むことで、実は今まで見てきたものはHaskellの強力な型推論があるからこそ実現できていたことなんだと分かり、そこからHaskellの型の世界へといざなわれていきます。

もう1点、本全体を通して登場する型クラスは、ShowReadNumなど基本的なものから、SemigroupMonoidFunctorApplicativeAlternativeMonad も登場しますが、これらの段階的な登場のさせ方と解説が秀逸なのです。「なるほど、だからこの型クラスがあるのか」と感じさせる。また、もともとHaskellの型クラスは、専用の構文があるので読みやすいのもありますが、それを更に図解していたり、Haskellの歴史も交えて解説している点が非常に良いです。

そう、本全体を通して感じたのが、累進性の実感の原理なのです。

単純なものから始めて、より興味深い視点や入り組んだ視点へと導く方法があります。 景観設計者(landscape architect)は連なった風景を設計するために累進性の実感(progressive realization)の原理を使います。景観設計者は、ものを意図的に隠して景観全体を渡り歩くまでは見えないようにするための、さまざまな眺め(view)を設計します。この考え方は、少しずつ、興味深い段階を踏んで、目指している目的地へと見物人を動かすというものです。あらゆる曲がり角に、新しく、興味深いものがあります。

John Simondsは著書『Landscape Architecture(邦題:ランドスケープ・アーキテクチュア)』の中で次のように述べています。「ある眺めは、計画上最も望ましいとした地点からだけ、最も印象深くその全貌を明らかにすべきである」。それぞれの眺めは、独自に魅力を発揮します。そして、新たな眺めは、それぞれ新たな驚きを含んでいます。累進性の実感により、曲がり角の向こうにあるものへの期待で楽しみが増えるのです。

出典元:「オブジェクトデザイン: ロール、責務、コラボレーションによる設計技法」レベッカ・ワーフスブラック / アラン・マクキーン 著

注意した方が良いところ

1点注意した方が良いところがあって、本の中で、依存ライブラリやデフォルトのGHC拡張の設定を .cabal ファイルに直接編集するように書かれていますが、Stackを使っている場合はpackage.yaml に以下のように記述すると、Stackにバンドルされているhpackが自動的に .cabal ファイルを生成するので、その方法で定義した方が楽だと思います。

dependencies:
- base >= 4.7 && < 5
- aeson
- bytestring
- text

default-extensions:
- OverloadedStrings
- DeriveGeneric

こちらの記事が詳しく解説されていますね。

qiita.com

おわりに

私は、Get Programming with Haskell によってHaskellへの扉が開かれました。次は何を学ぶかは、この本の最後にもヒントが書かれていますし、他にも読みたい本がたくさんあるので、また読んで面白かったらここに書きますね。

追記(2019/07/20)

この記事を公開してから知ったのですが、Get Programming with Haskell の翻訳版が今度出版されるそうです。「英語はちょっと…」という方はこちらをチェックしてみてはいかがでしょうか。

入門Haskellプログラミング

入門Haskellプログラミング

3年間悩み続けてようやく利用開始したSafari Books Onlineが最高だった件

先日、Safari Books Onlineの利用を開始したのですが、学びの世界が一気に広がりとても満足しています。今回はこの喜びを表現しようと、Safari Books Onlineについてとか、利用開始に至った経緯、それと、お得な利用方法について書きたいと思います!

Safari Books Onlineとは

Safari Books Onlineは、海外の200社以上の大手出版社から発行されている書籍、動画などをサブスクリプション型で提供しているデジタルライブラリーサービスです。残念ながら、今のところ日本語のコンテンツは無いようです。

www.oreilly.co.jp

ちなみに、今は「Online Learning with O’Reilly」という名称になったのでしょうか。「Safari Books Online」という名称が公式サイトから見当たらなくなりました。ですが、いまいちしっくりこないので、この記事では昔からの呼び名である「Safari Books Online」で書いていきたいと思います。

www.oreilly.com

利用開始までの長い道のり

実は、このサービス自体はだいぶ昔から知っていましたし、自分の読書スタイルからSafari Books Onlineを利用した方が絶対にお得というのは分かっていたものの、なかなか契約に踏み切れなかったんですね。というのは、小遣い制な私にとって月額$39または年額$399というのは微妙にハードルが高くて、これまで何度も検討しては断念というのを繰り返していたのです。そうこうしている内に、3年の月日が経ってしまいました。

ちなみに私の読書スタイルはこんな感じです。

  • その時の気分によって色んな本を並行読書している
  • 洋書は比較的よく読む
  • 大量の書籍に囲まれて生活していたい

すみません。最後のは願望ですね笑

あと、最近では読書以外に動画でも学ぶことが多くなりました。

利用開始に踏み切れたものは

そんな私がSafari Books Onlineの利用開始に踏み切れたのは、Optimizing Java という本がありまして、これをどうしても読みたかったからなんですね。

shop.oreilly.com

この本、Amazonだと5千円もする!どうせ5千円払うのならSafari Books Onlineを契約し、ついでに他の本も併せて読んだ方がお得なのでは。だけど小遣いが...

そんな時、以下の記事で ACM(Association for Computing Machinery) という、チューリング賞などで有名な米国の計算機学会の会員(年額$99)になると、特典としてSafari Books Onlineが利用できることを知りました。

410gone.click agnozingdays.hatenablog.com

記事を書いてくださった方々、めっちゃ感謝しています!即行で契約しました!

ACM会員の登録方法や、ACMアカウントでSafari Books Onlineを利用する方法については、上記のサイトで紹介されています。もちろん、Webブラウザだけでなく、モバイルアプリからも利用できます!

学びの世界はどう広がったか

圧倒的なコンテンツの量なので、大量の書籍に囲まれて生活していたい私の願望は満たされましたし、その中からその時の気分によって読みたい本をピックアップする感じで並行読書を楽しんでいます。もちろん、マルチデバイスで利用できるので、通勤中はタブレットのモバイルアプリで、自宅や職場でMacを触っているときはWebブラウザで読んでいます。読みたい本を探すときも、大量の書籍の中から串刺し検索で探せるのもいいですね。この機能で、今まで自分の知らなかった書籍にも巡り会えています。

f:id:shinharad:20190222192123p:plain

また、動画のトレーニングコースも充実しているので、最近だとiOSAndroidなど、モバイルアプリ開発の学習に利用しています。やはり、「ちょっと気になる技術がある」に対して最初の入口として動画で学び、深掘りしたくなったら書籍で学ぶというのはとても効率的です。

終わりに

今回は、Safari Books Online最高だったよ!という記事でした。

よく、企業のITエンジニア向けの福利厚生として、書籍購入補助制度があると思います。非常にありがたい制度ではあるのですが、大体の場合は企業の共有財産として購入するのでリアル本に限られたり、読み終わったら共有の本棚に戻す必要あったりすることが多いのではないでしょうか。大量の書籍に囲まれて生活していたい、いつでも読みたい本を自由に選びたい私にとっては、ちょっと物足りないというか...

そんな時、Safari Books Onlineにはチームプランや企業用プランもあるようです*1。ITエンジニア向けの福利厚生としてSafari Books Onlineが使えたら、私のような人がとても喜びます。一部の企業では既に導入済みのところもあるようなので、これがもっと広がるといいなと個人的に思っています。

macOS Mojaveにアップグレードして対処したこと

昨年11月にMacBook ProのOSをMojaveにアップグレードしましたが、今回から導入されたダークモードは個人的にかなり好みではあるものの、普段使いするのにとても困った事象に遭遇しました。今回は発生した事象とどう回避したかについて書きたいと思います。

スリープ中のバッテリー消費が激しくなった

これは、Mojaveアップグレード後の問題としてよく聞く事象だと思います。私の場合、自宅の MacBook Pro (Retina, 13-inch, Early 2015) をMojaveにアップグレードしたところ、この事象が発生するようになりました。

これが発生すると、例えば自宅でMacBook Proをフル充電してスリープモードのまま外出し、いざ使おうとしたら数%しか残っていない!みたいなことが何回かあって非常に困りました。

一部の記事では、macOSハイバネーション機能に問題があって、SMCをリセットすれば解消するみたいなことが書かれていましたが、私の場合それでは解消しませんでした。仕方がないので、電源アダプタを常時持ち歩くとか、使わないときは電源を落とすとかで、しばらく我慢を強いられる状況が続いていたんですね。

そして先日、別の理由でMacBook Proの環境をまっさらにしようと思い、OSのクリーンインストールをしたところ、この事象は嘘のように発生しなくなりました。

原因は結局分かりませんでしたが、今にして思うと一部のMojave未対応のアプリケーションが暴れてたのかなと推測しています。

Chromeでリンクをcommandキー+クリックしても新しいタブで開かなくなった

ページのリンク先を commandキー+クリック で新しいタブとして開いておき、後で順番に見ていくというのはよくやるのですが、お仕事用の MacBook Pro (15-inch, 2017) をMojaveにアップグレードしたところ、この操作をしても新しいタブで開かなくなってしまいました。

これは地味に困る事象で、仕方が無いので後で見るリンク先は毎回コンテキストメニューから「新しいタブを開く」をクリックすることで対処していました。(とても面倒くさい!)

その後、同じ症状で困っている人はいないかなと調べてみたところ、こちらの記事で対処法が紹介されていました。(ありがとうございます。とても助かりました!)

taktakf.hatenablog.com

どうやらUS配列のキーボードで、commandキーに英数/かな切り替えを割り当てるためにKarabiner-Elementsを使用していると発生してしまう事象のようです。

対処としては上記の記事で紹介されているように、commandキーの英数/かな切り替えをKarabiner-Elementsではなく、⌘英かな に変更することで回避することができました。

終わりに

今回発生した事象で、「スリープ中のバッテリー消費が激しくなった」は、自宅のMacBook Proで発生しましたが、お仕事用では発生していません。逆に「Chromeでリンクをcommandキー+クリックしても新しいタブで開かなくなった」は、お仕事用のMacBook Proで発生しましたが、自宅用では発生していません。

モノによって発生する事象が違うみたいですね...困ったことに。

「オブジェクトデザイン」を読んだ

「オブジェクトデザイン」という設計技法の本を読みました。

www.shoeisha.co.jp

オブジェクトデザインは、2007年9月に出版された本で、残念ながら今は絶版となっています。原著は2002年11月に出版されたこちらですね。

www.informit.com

実は先日たまたま図書館の蔵書にあるのを発見し、借りて読むことができたので、今回はこの本について書きたいと思います。

ちなみに、なぜ10年以上前に出版された本を読もうと思ったのかというと、最近までEric Evansの「ドメイン駆動設計」を読み返していたのですが、その中で「責務駆動設計」というキーワードが脳裏に焼き付いていて、ちょうど同じ頃に @j5ik2o さんの「ドメインオブジェクトの責務について」という記事の中でこの本の存在を知ったのがきっかけでした。

この本のテーマ

この本では、オブジェクト指向設計について次のように解説しています。

実世界に存在しないオブジェクトを考え出すことで、現実世界の情報、プロセス、相互作用、関係、そしてエラーでさえも表現します。生命のないものに対して、生命と知性を与えます。理解が困難な現実世界のオブジェクトを、よりシンプルで管理しやすいソフトウェアオブジェクトへと分割します。

オブジェクト指向ソフトウェア開発は、その根本において実世界の物理学に従わないものです。現実世界をオブジェクト機構にモデリングすることが私たちの目的ではありません。そのため、私たちには現実世界を新たに考え出す資格があります。

この、管理しやすいソフトウェアオブジェクトへと分割するために、ロール、責務、コラボレーションという観点から設計を考えていく、というのがこの本の全体的なテーマとなっています。

本の構成

この本は大きく2つの部分で構成されています。

前半の第1章から第6章は、設計概念や責務駆動設計の中心的原理、実践方法について書かれています。前半を読むことで、設計の目的である、一貫した使いやすいオブジェクトを作り上げるために、ロール、責務、コラボレーションがどう作用するのかについて考えるための準備ができます。

後半の第7章から第10章は、前半で得た知識をもとに、ドキュメンテーションやコラボレーションにおける信頼領域内外での戦略、システムの柔軟性について解説しています。

ロール、責務、コラボレーション

アプリケーションは相互作用するオブジェクトの集合であり、それぞれのオブジェクトには ロール(役割) を割り当てます。このロールについて、この本では以下のような単純化した ロールステレオタイプ でオブジェクトを分類することで、責務に注目しやすくしています。

  • 情報保持役(Information Holder): 情報を知り、情報を提供する
  • 構造化役(Structurer): オブジェクト間の関係と、それらの関係についての情報を維持する
  • サービス提供役(Service Provider): 仕事を行うが、一般に演算サービスを提供する
  • 調整役(Coordinator): 他のオブジェクトにタスクを委譲することでイベントに対応する
  • 制御役(Controller): 判断を行い、他のオブジェクトのアクションをしっかりと指示する

責務 は、オブジェクトについて大雑把に記述したもので、本から引用すると以下の3つの主要な項目を含んでいます。

  • オブジェクトが行う動作
  • オブジェクトが持つ知識
  • オブジェクトが他に影響を与える主要な判断

コラボレーション は、オブジェクトもしくはロール(またはこの両方)の相互作用のことですね。

これらを踏まえて本の前半では、初期の探究的設計で作り上げた概念モデルに対して、オブジェクトを見つけ出し、ロールステレオタイプでオブジェクトの役割を単純化したうえで、それぞれの責務やコラボレーションを考えていくという流れで解説しています。あと、ロールや責務に応じたオブジェクトの名前付けのガイドラインについても解説があるので、個人的にとても参考になりました。

累進性の実感

もうひとつ、この本の中で印象に残った箇所について紹介します。

第7章「コラボレーションの記述」では、設計したオブジェクトをどのようにチームに伝えるかという、ドキュメンテーションの話になっています。この中で印象的だったのが、

7.8.2 ストーリーを展開する

単純なものから始めて、より興味深い視点や入り組んだ視点へと導く方法があります。 景観設計者(landscape architect)は連なった風景を設計するために累進性の実感(progressive realization)の原理を使います。景観設計者は、ものを意図的に隠して景観全体を渡り歩くまでは見えないようにするための、さまざまな眺め(view)を設計します。この考え方は、少しずつ、興味深い段階を踏んで、目指している目的地へと見物人を動かすというものです。あらゆる曲がり角に、新しく、興味深いものがあります。

John Simondsは著書『Landscape Architecture(邦題:ランドスケープ・アーキテクチュア)』の中で次のように述べています。「ある眺めは、計画上最も望ましいとした地点からだけ、最も印象深くその全貌を明らかにすべきである」。それぞれの眺めは、独自に魅力を発揮します。そして、新たな眺めは、それぞれ新たな驚きを含んでいます。累進性の実感により、曲がり角の向こうにあるものへの期待で楽しみが増えるのです。

ソフトウェアの設計者も、読み手がコラボレーションの景観を渡り歩くにつれてより深く理解するように仕向けることができます。

これは、ドキュメンテーションに限った話ではなく、例えばプログラミングであれば、宣言的にWHATを明示し、必要になったらHOWを探求させるような構成で書いておけば、累進性の実感を促すことにつながるのかなと思いました。

終わりに

オブジェクトデザインは非常に学びの多い本でした。

今回紹介した内容以外にも、実践するためのガイドラインが多く書かれています。 もちろん、10年以上前に出版された本なので、内容が古い部分もあるのですが、それらは脳内で補完しながら読む必要があります。

個人的には、恐らく1回読んだだけでは理解できていない部分があると思うので、間隔を空けて数カ月後にもう一度読んでみたいと思います。

Monix v3.0.0-RC2からTask.applyの挙動が変わっている

最近、Monix というScalaの非同期プログラミング用ライブラリを使い始めました。

monix.io

最初は、最新安定版である v2.3.3 で色々触ってみて「これは使える!楽しい!」となって、v3.x 系の方はどんな感じかなと思いバージョンを上げてみると、メソッド名をはじめ、色々変わりまくっていることに焦りました。その中で Task.apply の挙動の変更には注意が必要だなと思ったので書いておきます。

v3.x系でのTask.applyの変更

v2.x 系では、以下のコードは非同期処理になっていたと思います。

val task = Task { // Task.apply
  1 + 2
}

ところが、v3.x 系ではこの挙動が同期処理に変わるようです。つまり、Task.applyTask.eval は同じ挙動になる。

Task.applyのコードを比較してみる

それでは、v2.x 系と v3.x 系の Task のコードを比較してみましょう。以下は抜粋です。

Monix v2.3.3

object Task extends TaskInstances {
  /** Returns a new task that, when executed, will emit the result of
    * the given function, executed asynchronously.
    *
    * @param f is the callback to execute asynchronously
    */
  def apply[A](f: => A): Task[A] =
    fork(eval(f))

https://github.com/monix/monix/blob/v2.3.3/monix-eval/shared/src/main/scala/monix/eval/Task.scala#L662-L669

Monix v3.0.0-RC2

object Task extends TaskInstancesLevel1 {
  /** Lifts the given thunk in the `Task` context, processing it synchronously
    * when the task gets evaluated.
    *
    * This is an alias for:
    *
    * {{{
    *   val thunk = () => 42
    *   Task.eval(thunk())
    * }}}
    *
    * WARN: behavior of `Task.apply` has changed since 3.0.0-RC2.
    * Before the change (during Monix 2.x series), this operation was forcing
    * a fork, being equivalent to the new [[Task.evalAsync]].
    *
    * Switch to [[Task.evalAsync]] if you wish the old behavior, or combine
    * [[Task.eval]] with [[Task.executeAsync]].
    */
  def apply[A](@deprecatedName('f) a: => A): Task[A] =
    eval(a)

https://github.com/monix/monix/blob/v3.0.0-RC2/monix-eval/shared/src/main/scala/monix/eval/Task.scala#L2376-L2395

v3.x 系のコメントにこのような記述があります。

WARN: behavior of Task.apply has changed since 3.0.0-RC2. Before the change (during Monix 2.x series), this operation was forcing a fork, being equivalent to the new Task.evalAsync.

以下は機械翻訳

警告:Task.applyの動作が3.0.0-RC2以降に変更されました。変更前(Monix 2.xシリーズ中)、この操作は新しいTask.evalAsyncと同等のフォークを強制していました。

つまり、v3.x 系で非同期な Task を使いたかったら Task.apply ではなく Task.evalAsync を使ってねということみたいです。

終わりに

今回の変更を受けて、 今後は Task.apply ではなく、Task.evalAsync で非同期なのか Task.eval で同期なのかを明示的に書いた方が良いのかなと思いました。v3.x 系では他にも Callback が任意のエラー型を設定できるようになってたりと大きな変更があるみたいですね。

セールを利用してMartin FowlerのRefactoringとMichael NygardのRelease It!を少しお安く購入した話

前回は海外の出版社のセールについて書きました。

shinharad.hateblo.jp

私は早速このセールを利用して、以下の2冊を購入しました。いずれもeBookです。

今回の買い物でどのくらい安くなったかというと、

  • Refactoring: Improving the Design of Existing Code, 2nd Edition
    • List Price: $47.99
    • Discount: -$16.80 (BLACK FRIDAY SALE Buy 1, Save 35%)
    • Subtotal: $31.19
  • Release It! Second Edition
    • List Price: $25.95
    • Discount: -$10.38 (Annual Black Friday Sale 40%OFF)
    • Subtotal: $15.57

合計で $46.76 でした。定価で買うと $73.94 なのでお得な買い物でした!

この時期は洋書の技術書をお得に買おう!

毎年恒例ですが、11月下旬から12月末にかけてのこの時期は、海外の出版社が相次いで年間最大規模のセールへ突入するので、洋書の技術書がお得に買えますよ、という話。

普段Safari Books Onlineなどのサブスクリプションサービスを利用していない人にとっては、この時期のセールを狙ってまとめ買いをしている人も多いのではないでしょうか。

今回は、Manning Publications、Packt Publishing、Apress、The Pragmatic Bookshelf、InformITのセールについて書きたいと思います。

Manning Publications

まずは、安心と信頼 *1 のManningです。 Manningは、毎年12月になると年末のカウントダウンセールとして、日替わりで何かしら安くなります。何が安くなるかは、特設サイトで毎日発表しています。今回であればここですね。

www.manning.com

ちなみに、日によっては電子書籍が全て半額とか、Videoが全て半額とかやるので、私の場合はその日を狙って購入しています。

Packt Publishing

Packtは、11/22現在Black Fridayで全品$10セールをやってますが、例年だと12月に更にお得な$5セールを開催しています。確実に開催されるかどうかは分からないですが、今回の$10セールは見送って$5セールを待ってみるというのも手ですね。ちなみにここ数年は毎年開催されていたと思います。

www.packtpub.com

Apress

Apressも現在Cyber Monday Saleで、eBookが全品$7と今ならお得に買えるようです。

www.apress.com

Apressの場合、Practical NATSみたいなニッチな書籍 *2 も扱っているので、ラインナップを見ているだけでも楽しいかもしれません。

www.apress.com

The Pragmatic Bookshelf

The Pragmatic Bookshelfは、現在Annual Black Friday Saleとして全品40%OFFとなってます。

Annual Black Friday Sale | The Pragmatic Bookshelf

Programming Clojure, Third Edition を安く買えるチャンスですね!

InformIT

InformITは、現在Black Friday Saleとして1冊購入で35%OFF、2冊以上購入で55%OFFとなってます。

www.informit.com

終わりに

海外の出版社の面白いところは、豊富なコンテンツだけでなく、これから出版予定の本も併せてセール対象になるところだと思います。 是非このセールを利用してお得にまとめ買いしちゃいましょう!

*1:個人の感想です

*2:NATSを扱った唯一の書籍?