Skip to the content.

基本型

なぜ型が重要か

型を定義する3つの方法

type

型シノニム

data

代数的データ型とは”足し算”と”掛け算”が出来るような型のこと。”足し算”はEither a b、”掛け算”は(a, b)と対応する。

Codata

newtype

既存の型と同型な別の型を定義することができるが、コンパイル後の表現は既存の型と同一になるので効率の面で利点がある。1つの値コンストラクタと1つのフィールドを持つdataで定義された型との違いは以下のように現れる。

> newtype A = A Int
> checkA (A _) = "OK"
> chackA undefined
"OK"

> data B = B Int
> checkB (B _) = "OK"
> checkB undefined
"*** Exception: Prelude.undefined

型注釈

  1. Type annotations for an external function may require not only its type structure, but also references to the type names or implementations (i.e. import of modules where these types are declared).
  2. Partial type signatures still require the type structure of the function (making use of the scaffold of the type signature).
  3. Visible type applications is the tersest and cleanest way to annotate an external function’s type. It does not require re-building of the type signature in case of ambiguity.

Тех-Детали: Type annotations vs partial type signatures vs visible type applications

多相型

レコード

関数

パターンマッチ

多変数関数とカリー化

curry :: ((a, b) -> c) -> a -> b -> c
uncurry :: (a -> b -> c) -> (a, b) -> c

Haskell 初心者は括弧ばかりの Lisp のようなコードを書く。中級者になると、($) が多くなる。上級者(言い過ぎか?)になると、($) が消えて、(.) が多くなる。

出典: 関数合成の妙技

ポイントフリー

必要のないところでポイントワイズに書く必要はないが、あまりポイントフリーに拘りすぎないのも大事

遅延評価

One very interesting comparison is that lazy evaluation is to the CPU what garbage collection is to memory.

出典: http://scott.sauyet.com/Javascript/Talk/2014/01/FuncProgTalk/#slide-40

メモ化

遅延評価を利用したメモ化の実装例

fibs :: [Integer]
fibs = map fib [0..]

fib :: Int -> Integer
fib 0 = 1
fib 1 = 1
fib n = fibs !! (n-1) + fibs !! (n-2)

参考: Can someone explain the concept behind Haskell’s memoization?

正格評価

部分関数

多相型

命名規則

演算子