Real World Haskell - 第2章

Real World Haskell を継続的に勉強中。

型と関数

Chapter 2. Types and Functions

Haskell's type system
  • strong types
    • 勝手に型を変換して解釈することが無いので、コンパイル時に型に関するバグが必ずとれる
    • well typed と ill typed
  • static types
    • コンパイル時(実行前)に全ての値の型を評価する
    • static typing では duck typing が難しいが、typeclasses を使えば dynamic typing 可能
  • type inference
What to expect from the type system
Some common basic types
  • 基本的な型
    • Char
    • Bool
    • Int
      • 値の範囲はシステムに依存
    • Integer
      • 値の範囲に制限がない
      • オーバーフローしないけど Int よりパフォーマンスが悪い
    • Double
  • :: Type は type signature と呼ぶ
Function application
  • 関数使うには関数名の後に引数を並べて書く
    • 括弧とかカンマとか要らないけど、必要なら使う

ghci> (compare 2 3) == LT
True
ghci> compare 2 3 == LT
True
ghci> compare (sqrt 3) (sqrt 6)
LT

Useful composite data types: lists and tuples
  • リストとタプル
    • リストの型は polymorphic
    • type variable
      • [Int] は Int 型の値のリスト
      • Int は [Int] 型の値のリスト
    • タプルは異なる型の値を持てる固定長のコレクション

ghci> :type (True, "hello")
(True, "hello") :: (Bool, [Char])
ghci> (4, ['a', 'm'], (16, True))
(4,"am",(16,True))

      • () は C の void みたいなもの
    • unit, pair (2-tuple), triple (3-tuple), ...
Functions over lists and tuples
  • Passing an expression to a function

ghci> head (drop 4 "azerty")
't'

  • Function types and purity
    • In Haskell, the default is for functions to not have side effects: the result of a function depends only on the inputs that we explicitly provide. We call these functions pure; functions with side effects are impure.
    • If a function has side effects, we can tell by reading its type signature: the type of the function's result will begin with IO.

ghci> :type readFile
readFile :: FilePath -> IO String

Haskell source files, and writing simple functions
add a b = a + b
  • haskell の関数には所謂 return は無い
  • When you see an = symbol in Haskell code, it represents “meaning”: the name on the left is defined to be the expression on the right.
  • Just what is a variable, anyway?

In Haskell, a variable provides a way to give a name to an expression. Once a variable is bound to (i.e. associated with) a particular expression, its value does not change: we can always use the name of the variable instead of writing out the expression, and get the same result either way.

  • Conditional evaluation
myDrop n xs = if n <= 0 || null xs
              then xs
              else myDrop (n - 1) (tail xs)

In Haskell, indentation is important: it continues an existing definition, instead of starting a new one. Don't omit the indentation!

You might wonder where the variable name xs comes from in the Haskell function. This is a common naming pattern for lists: you can read the s as a suffix, so the name is essentially “plural of x”.

Understanding evaluation by example
  • Lazy evaluation
  • Haskell は non-strict evaluation (lazy evaluation)
    • 本当に必要になるときまで値を評価しない
    • The record that we use to track an unevaluated expression is referred to as a thunk.
Polymorphism in Haskell
  • Parametric polymorphism
    • Java の generic や C++ の template みたいなもの
  • subtype polymorphism
    • subclassing とか
    • Haskell には無い
  • coercion polymorphism
    • C の int -> float の自動キャストとか
    • Haskell には無い
The type of a function of more than one argument
  • Type Signature の -> は right-associative

take :: Int -> ([a] -> [a])

  • the type signature as a function that takes one argument, an Int, and returns another function.
Why the fuss over purity?
  • コードが読みやすい
  • セキュリティに効果的

参考