書籍概要

Haskell入門 関数型プログラミング言語の基礎と実践

著者
発売日
更新日

概要

基礎文法から実践的なアプリケーション開発までしっかりわかるHaskellの入門書です。型,関数,モナド,並列並行などHaskellの重要な考え方と実際にアプリケーション開発を行うまでをわかりやすく解説しています。

こんな方におすすめ

  • Haskellに入門したい人
  • Haskellの基礎を学んで実践的なアプリケーション開発をしてみたい人
  • 関数型プログラミングの技法を身に付けたい人

サンプル

目次

第1章 はじめてのHaskell

  • 1.1 Haskell の特徴
  • 1.2 実行環境の構築
  • 1.3 REPL とスクリプトの実行
  • 1.4 プロジェクト作成とビルド

第2章 基本の文法

  • 2.1 文法の特色
  • 2.2 基本のデータ型
  • 2.3 変数
  • 2.4 関数
  • 2.5 main 関数とdo 式
  • 2.6 条件分岐とパターンマッチ
  • 2.7 データ構造
  • 2.8 ループの実現
  • 2.9 モジュールとパッケージ

第3章 型・型クラス

  • 3.1 型の記述
  • 3.2 型システム
  • 3.3 型コンストラクタと型変数
  • 3.4 代数的データ型
  • 3.5 レコード記法
  • 3.6 再帰的な定義
  • 3.7 型の別名
  • 3.8 型クラス
  • 3.9 型制約
  • 3.10 Preludeにおける型クラス

第4章 I/O処理

  • 4.1 IO 型
  • 4.2 コマンドライン引数と環境変数
  • 4.3 入出力
  • 4.4 ファイルシステム
  • 4.5 例外処理

第5章 モナド

  • 5.1 モナドアクション
  • 5.2 Monad の性質を利用する
  • 5.3 Functor とApplicative
  • 5.4 Either eモナドとExcept e モナド
  • 5.5 Reader r モナド
  • 5.6 ST s モナド
  • 5.7 リストモナド
  • 5.8 モナド変換子

第6章 関数型プログラミング

  • 6.1 型とプログラミング
  • 6.2 関数による抽象化
  • 6.3 代入文と変数の局所性
  • 6.4 型クラスと拡張性

第7章 ライブラリ

  • 7.1 標準ライブラリ
  • 7.2 GHCに付属するライブラリ
  • 7.3 効率的な文字列操作 ─ ByteString・Text
  • 7.4 高速にランダムアクセス可能な配列 ─ vector
  • 7.5 高速なパーサ ─ attoparsec
  • 7.6 型安全なJOSN 操作 ─ aeson
  • 7.7 日付・時刻を扱う ─ time
  • 7.8 複雑なデータ構造への効率的なアクセス ─ lens
  • 7.9 モナドによるDSL の実現 ─ operational
  • 7.10 ストリームデータ処理 ─ pipes

第8章 並列・並行プログラミング

  • 8.1 並列と並行
  • 8.2 MVarによるスレッド間の通信
  • 8.3 STM によるスレッド間の通信
  • 8.4 非同期例外
  • 8.5 より安全な非同期 ─ async
  • 8.6 並列性を実現するライブラリ

第9章 コマンドラインツールの作成

  • 9.1 開発の準備
  • 9.2 HUnit による自動テスト
  • 9.3 パーサの作成
  • 9.4 クエリの実行とIO 処理
  • 9.5 まとめ

第10章 Webアプリケーションの作成

  • 10.1 Web アプリケーション環境の選定
  • 10.2 開発の準備
  • 10.3 モデルの開発
  • 10.4 コントローラの開発
  • 10.5 ビューの開発
  • 10.6 実行ファイルの作成
  • 10.7 まとめ

第11章 サーバとクライアントの連携

  • 11.1 開発の準備
  • 11.2 クライアント・サーバシステムの簡易実装
  • 11.3 オークションシステムの構築
  • 11.4 オークションシステムのクライアントプログラム
  • 11.5 まとめ

サポート

ダウンロード

サンプルファイルのダウンロード

(2017年10月26日更新)

本書のサンプルファイルをご利用いただけます。
サンプルファイルの利用方法についてはzipファイル内のREADME.mdを参照してください。
https://github.com/hiratara/Haskell-Nyumon-Sampleからgitでも取得できます。

ダウンロード
サンプルファイル

正誤表

書籍の内容に誤りのあったことをおわびいたします。

(2018年8月20日最終更新)

P.182 型の表記

catchE :: Except e' a -> (e -> Except e a) -> > Except e a
catchE :: Except e a -> (e -> Except e' a) -> Except e' a

P.274 関数名

findAmount
findPrice

(以下,2017年10月26日更新)

初版第1刷
P.25 脚注10

中値演算子とあえて書いているように Haskell では中置しない演算子もあります。ただし、Haskell における演算子はほぼすべて 2 つの項 (2 引数) をとる中値演算子です。
2.4.5 で解説します。
中置演算子とあえて書いているように Haskell では中置しない演算子もあります。ただし、Haskell における演算子はほぼすべて 2 つの項 (2 引数) をとる中置演算子です。
2.4.5 で解説します。

P.30 コラム「文字のコードポイント」

Enum は列挙型 (enumeration) の略で、順に番号を振れるデータの型に対して使う関数です。
Enum は列挙型 (enumeration) の略で、順に番号を振れるデータの型に対して使う型クラスです。

P.43 ページ下部のリスト

 – (x + 1) ˆ 2 引数と区別するために f . g にかっこを付ける


 – (3 + 1) ˆ 2 引数と区別するために f . g にかっこを付ける

P.44 コラム内の表記

\x y -> (x + 2) * (3 + y)
\x y -> (2 + x) * (3 + y)

P.49 ページ下部の本文

中値演算子は (と) で囲むことで通常の関数と同じように利用できます。第一引数が中値演算子の左側、第二引数が中値演算子の右側だったものになると覚えてください。
中置演算子は (と) で囲むことで通常の関数と同じように利用できます。第一引数が中置演算子の左側、第二引数が中置演算子の右側だったものになると覚えてください。

P.75 本文

() で明示的に参照する識別子を列挙するか、qualifiedas を使ってどのモジュール由来の識別子なのか区別できるように修飾しておくのがいいでしょう。
() で明示的に参照する識別子を列挙するか、qualified … as を使ってどのモジュール由来の識別子なのか区別できるように修飾しておくのがいいでしょう。

P.92 脚注 29

以後も同様に derving 句を指定します。
以後も同様に deriving 句を指定します。

P.104 本文

例えば、Either a b 型 (2.7.4 参照) ととともに アプリケーション内で
例えば、Either a b 型 (2.7.4 参照) とともにアプリケーション内で

P.136 最上段のリスト

最上段の何もしない Prelude>を入力する必要はありません。

P.142 コラムのリスト

あらかじめ import System.IO しておく必要があります。

P.151 本文

同じく System.Drectory モジュールの
同じく System.Directory モジュールの

P.153 コラム

System.Drectory モジュールの
System.Directory モジュールの

P.154 コラム 「Windows の実行ファイル対策」

いずれの実行例も,+ではなく++にする。


Prelude System.Directory > findExecutable $ "ghc" + exeExtension
Prelude System.Directory > findExecutables $ "ghc" + exeExtension


Prelude System.Directory > findExecutable $ "ghc" ++ exeExtension
Prelude System.Directory > findExecutables $ "ghc" ++ exeExtension

P.161 本文

throwMyException 関数が引数の値によって独自の例外を thorwIO で発生させます。
throwMyException 関数が引数の値によって独自の例外を throwIO で発生させます。

P.169 リスト

誤っていたのでまるまる差し替えてください。

 game :: [Card] -> [(Score, Hand, Player)]


 game :: Stock -> [(Score, Hand, Player)]

P.178 本文

Human データコンストラクタは、Strig -> Int -> Gender…
Human データコンストラクタは、String -> Int -> Gender…

P.190 本文

第二引数で指定した初期値のリストの長さがが配列のサイズよりも
第二引数で指定した初期値のリストの長さ配列のサイズよりも

P.216 下部のリスト

filePath の大文字小文字表記が誤っていました。


concatMultiFiles filePaths dst =
handleMultiFiles filepaths (\ hdl -> copyFile hdl dst)



concatMultiFiles filePaths dst =
handleMultiFiles filePaths (\ hdl -> copyFile hdl dst)

P.219 リスト

本来必要な do が抜けていました。


handleMultiFiles filePaths $ \hdl ->
hClose hdl



handleMultiFiles filePaths $ \hdl -> do
hClose hdl

P.223 リスト

インデントが紙面上では誤っていました。


class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
max , min :: a -> a -> a



class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
max , min :: a -> a -> a

P.224 下部のリスト

コードの一番上に{-# LANGUAGE FlexibleInstances #-}を追加します。

P.240 下部のリスト

simon :: Text など実行できない例が含まれていました。


ghci > :set -XOverloadedStrings
ghci > import qualified Data.Text as T
ghci > simon :: Text
ghci > simon = "Many Simons ."
ghci > :t T.pack
T.pack :: String -> Text
ghci > :t T.unpack
T.unpack :: Text -> String



ghci > :set -XOverloadedStrings
ghci > import qualified Data.Text as T
ghci > simon = "Many Simons ." :: T.Text
ghci > :t T.pack
T.pack :: String -> T.Text
ghci > :t T.unpack
T.unpack :: T.Text -> String

P.250 ページ最上部のリスト

コード中から明らかではない,Animal の定義については data Animal = Dog | Pig derivingShow としてください。

P.254 下部のリスト

1 行目の import を言語拡張の指定に変更します。


import qualified Data.Text as T



{-# LANGUAGE OverloadedStrings #-}

P.258 下部のリスト

deriveJSON defaultOptions ”Human の記述がないとエンコードに失敗します。

P.259 ページ下部のリスト

encode だけでは出力できないので、適宜 B.putStrLn と組み合わせてください。


data IntStr = IntData Int | StrData String
encode $ IntData 999
encode $ StrData "World !"


data IntStr = IntData Int | StrData String
B.putStrLn $ encode $ IntData 999
B.putStrLn $ encode $ StrData "World !"

P.260 2 つめのリスト

誤っていたのでまるまる差し替えてください。
コードの一番上に{-# LANGUAGE OverloadedLists,OverloadedStrings #-}を追加します。


nameListValue :: Value


{-# LANGUAGE OverloadedLists #-}
nameListValue :: Value

P.263 コラム「インスタンスの自前実装」の中段のリスト

言語拡張とライブラリの指定が抜けていました。


data Person = Person


{-# LANGUAGE OverloadedStrings #-}
import Data.Aeson
import Data.Aeson.Types
data Person = Person

P.263 コラム「Generics の利用」のリスト

import Data.Aeson が抜けていました。


{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics



{-# LANGUAGE DeriveGeneric #-}
import GHC.Generics
import Data.Aeson

P.269 UserName の定義

userName :: Functor f => Lens User User String String
userName :: Lens User User String String

P.311 本文

Stack による hjq.cabal の初期の設定では、テストは src ディレクトリ次のモジュールを読み込むようになっているため、すぐにテストが書ける
Stack による hjq.cabal の初期の設定では、テストは src ディレクトリ以下のモジュールを読み込むようになっているため、すぐにテストが書ける

P.313 本文

さっそく、HUnit ライブラリを提供している HUnit パッケージを build-depends に追加しましょう。 hs-source-dirs を次のようにします。
さっそく、HUnit ライブラリを提供している HUnit パッケージを build-depends に追加しましょう。 test-suite を次のようにします。

P.318 本文(1 段落目)

このテストがグリーンになるように実装 (JqFilterParser) を修正しなくてはいけません。
このテストがグリーンになるように実装 (jqFilterParser) を修正しなくてはいけません。

P.318 本文(リストの下に続く文章)

これで、jqFilterparserTest も成功するようになりました。
これで、jqFilterParserSpacesTest も成功するようになりました。

P.326 脚注 11

インストールせず試したいときは stack build 後に stack exec hjq と実行して下さい。
インストールせず試したいときは stack build 後に stack exec hjq-exe と実行して下さい。

P.340 本文

RDBMS に対応したデータ型生成用のドライバ、スキーマ名、テーブル名、driving 句に追加する型クラス名を渡す必要があります。
RDBMS に対応したデータ型生成用のドライバ、スキーマ名、テーブル名、deriving句に追加する型クラス名を渡す必要があります。

P.341 脚注 25

スキーム名とは SQLite ではデータベース名のことであり、
スキーマ名とは SQLite ではデータベース名のことであり、

P.349 本文

Model.WeightRecorder についても同様にデータ登録と読み込みを実装します。
Model.WeightRecord についても同様にデータ登録と読み込みを実装します。

P.359 本文

続いて data-files 次のファイルにアクセスするための、特殊なモジュールを import します。
続いて data-files 以下のファイルにアクセスするための、特殊なモジュールを import します。

P.369 脚注 61

外部へのインタフェースなのに対し、src/Web.WeightRecorde.hs はアプリケーション本体としてここでは記述しています。
外部へのインタフェースなのに対し、src/Web.WeightRecorder.hs はアプリケーション本体としてここでは記述しています。

P.377 本文

src では Clien.hs と Server.hs に加えて…
src では Client.hs と Server.hs に加えて…

P.386 本文

次の内容を最後にまとめて書いて、starck runghc counter.hs で実行しましょう。
次の内容を最後にまとめて書いて、stack runghc counter.hs で実行しましょう。

P.387 コラム

ライブラリ依存の部分を適切にを切り出すと方法などがあります。
ライブラリ依存の部分を適切に切り出す方法などがあります。

P.389 本文

返り値はオークションが開催していない場合を考慮して Maybe AucitonItem とします。
返り値はオークションが開催していない場合を考慮して Maybe AuctionItem とし ます。

(以下,2017年9月26日更新)

目次,P.256

型安全なJOSN操作 - aeson
型安全なJSON操作 - aeson

P.44 「ポイントフリースタイルによる可読性の悪化」

\x y -> (x + 2) * (y + 3)
\x y -> (2 + x) * (3 + y)

P.60 リスト


Prelude> case x of (x1, x2) -> print x2


Prelude> case x of (x1, x2) -> x2

P.73 リスト


module Main(main) where import Params


module Main(main) where
import Params

P.161 最下部のリスト

正しくは黒背景です。

P.169 リスト


game :: [Card] -> [(Score, Hand, Player)]


game :: Stock -> [(Score, Hand, Player)

P.245 リスト

import Control.Monadは必要ありません。

P.245 最下部のリスト

次の修正に加えて,背景色は黒色です。


fromList ["Dog", "Pig", "Cat", "Wolf", "Mouse", "Cow", "Horse"]


["Dog", "Pig", "Cat", "Wolf", "Mouse", "Cow", "Horse"]

P.260 リスト


nameListValue :: Value



{# LANGUAGE OverloadedLists}
nameListValue :: Value


P.271 「Prism」によるデータアクセス内のリスト


他の関数も使うのでControl.Lens.Prismまでしてしない


他の関数も使うのでControl.Lens.Prismまで指定しない

P.301 リスト


getUrl :: Request -> IO L8.ByteString


getUrl :: Request -> IO C8.ByteString

補足情報

(2017年10月26日更新)

本書では一部のリスト(ソースコード)について,重要部分を抜粋して表記しています。動作が不明な点はサンプルファイルと合わせてご確認ください。

P.141 コラム『標準入力とBufferMode』の動作

(2018年3月20日更新)

WindowsではGHCの不具合により書籍で解説した通りには動作しません。

商品一覧