SlideShare ist ein Scribd-Unternehmen logo
1 von 50
「すごいHaskellたのしく学ぼう!」第7章

型や型クラスを
         自分で作ろう
    第3回 スタートHaskell2
       2012年8月19日
        @a_hisame
自己紹介

• あひさめ(@a_hisame)
• 社会人2年目
  • 今のところはSIerさんのお仕事メイン
• Haskell学習は3度目の正直
• プログラミング、アナログゲーム全般、料理・お酒など
7.1 データ型

• 様々なデータ型
• Bool, Int, Char, Maybe, ... etc
• dataキーワードで新しいデータ型を定義


-- Bool型を定義
data Bool = False | True


                                      新しいデータ型「Bool」を定義
                          このBool型はFalse、または、Trueの値を取り得る
                                    (これらは値コンストラクタでもある)
                データ型名、値コンストラクタは大文字で始まる必要がある
7.2 形づくる

-- フィールドの必要ないデータ型
data Bool = False | True


-- フィールドを持つデータ型
data Shape = Circle Float Float Float
  | Rectangle Float Float Float Float


ghci > :t Rectangle
Rectangle :: Float -> Float -> Float -> Float -> Shape

                                    Circle, Rectangleは値コンストラクタ
                  その後に渡す値を持つ、定義したデータ型の値を返す関数
7.2 形づくる


• 図形(Shape)の面積を求める関数を定義


area :: Shape -> Float
area ( Circle _ _ r ) = pi * r ^ 2
area ( Rectangle x1 y1 x2 y2 ) =
                       (abs $ x2-x1) * (abs $ y2 - y1)



               area関数はShape型を受け取り、その面積(Float)を返す関数
                 引数のShape型を受け取る部分でパターンマッチを行い
                                 型ごとに適切な実装を行っている
                 (この関数は任意のShape型の値を引数として受け取れる)
7.2 形づくる
• ghci上で次のコードを実行する
data Shape = Circle Float Float Float
  | Rectangle Float Float Float Float
Circle 10 20 5

        <interactive>:19:1:
           No instance for (Show Shape)
            arising from a use of `print'
           Possible fix: add an instance declaration for (Show Shape)
           In a stmt of an interactive GHCi command: print it




      Shapeというデータ型の値を文字列として表示する方法が分かりません
       (ghci上で実行した場合、その値の文字列表現を結果として表示する)
7.2 形づくる
• Shape型の定義に次の一文を追加

data Shape = Circle Float Float Float
  | Rectangle Float Float Float Float
  deriving (Show)
Circle 10 20 5




                              deriving (Show) をつけることで、
              Shapeデータ型の各値を文字列でどのように表現するかを
                          自動的に実装してくれる(詳しくは後述)
7.2 形づくる
• ところで・・・
data Shape = Circle Float Float Float
  | Rectangle Float Float Float Float
  deriving (Show)
Circle 10 20 5

        Circleの10, 20, 5というのは何を表している?
        Circle [中心のX座標] [中心のY座標] [円の半径] を想定
        しているが、この順番を間違えてしまうかも。



      Shapeというデータ型の値を文字列として表示する方法が分かりません
       (ghci上で実行した場合、その値の文字列表現を結果として表示する)
7.2 形づくる
• Point型を定義
data Point = Point Float Float deriving (Show)
data Shape = Circle Point Float
  | Rectangle Point Point deriving (Show)
Circle (Point 10 20) 5

  Circle [中心座標] [円の半径] ということを型で表現できる




                                  データ型を表現するために
                   新たなデータ型を定義して使用することができる
7.2 形づくる


• 図形(Shape)の面積を求める関数を修正


area :: Shape -> Float
area ( Circle _ r ) = pi * r ^ 2
area ( Rectangle (Point x1 y1) (Point x2 y2) ) =
                       (abs $ x2-x1) * (abs $ y2 - y1)




          area関数はShape型を受け取り、その面積(Float)を返す関数(修正版)
              データ型の中のデータ型もパターンマッチの対象にできる。
7.2 形づくる
• モジュールとしてエクスポート
module Shapes (
  Point(..), Shape(Circle, Rectangle),
  area, baseCircle
) where

        データ型、値コンストラクタ(関数)、関数のエクスポート


-- 値コンストラクタをエクスポートしない場合
module Shapes (Point, Shape) where


      モジュールとしてデータ型、値コンストラクタを個別にエクスポートできる
                  値コンストラクタを提供せず、生成用の関数を提供することで
                    値コンストラクタを使ったパターンマッチはできなくなるが
                          既存のプログラムを壊さずに型の内部表現が変更可能
7.3 レコード構文

• 名前付きのフィールドを備えたデータ型の作成
data Person = Person {
  firstName :: String
, lastName :: String
, age :: Int
, height :: Float
, phoneNumber :: String
, flavor :: String } deriving (Show)

   フィールド名 :: フィールドの型

                                  作成したデータ型のフィールドに
                        それぞれ名前を持たせたデータ型を作成できる
7.3 レコード構文

• 値の作成と自動生成される関数
-- フィールド名の関数(データ型 -> フィールド)を自動生成する

ghci> :t flavor
flavor :: Person -> String

-- レコード型の値を生成する(カンマ区切りでフィールドに値を設定)

ghci> let p = Person { firstName = “Buddy”,
 lastName = “Finklestein”, age = 43, height = 184.2,
 phoneNumber = “526-2928”, flavor = “Chocolate” }


           レコード型のパラメータを名前付きで全て指定する(順序は自由)
モジュールで値コンストラクタの指定をしなくてもレコード型の値を生成できる
 Q. レコード型の値をエクスポートするときにそれを公開しないようにできる?
7.4 型引数

• 値コンストラクタと型コンストラクタ

data Point = Point Float Float deriving (Show)
data Maybe a = Nothing | Just a
                      このaが型引数

ghci> Point 5 10      (型を与えることで使用する具体型が決定される)

ghci> Point “x” “y”    -- ERROR
ghci> Just 10          -- (Num a) => Maybe a
ghci> Just “string”    -- Maybe [Char]

       値コンストラクタ:値を受け取って新しい値(Ex. Point 5.0 10.0)を作る
          型コンストラクタ:型を受け取って新しい型(Ex. Maybe Int)を作る
                 (この例では単なるMaybeという型の値は存在できないが
                                Maybe Intという型の値は存在できる)
7.4 型引数

• 様々な型を格納するデータ型が作れる

data Maybe a = Nothing | Just a

-- もしも型引数がなければ...

data IntMaybe = INothing | IJust Int
data StrMaybe = SNothing | SJust String

ghci> Just 10 :: Maybe Int
ghci> Just “string” :: Maybe String



                    異なるデータ型ごとにデータを作る必要がなくなる
7.4 型引数
• 多相的
functionA :: Maybe Int -> String
functionB :: Maybe String -> String


ghci> :t []
[] :: [a] -- ([] a)と意味は同じ
ghci> :t (++)
(++) :: [a] -> [a] -> [a]

       MaybeのNothingはfunctionA, functionBのどちらの引数としても扱える
                               Nothingの型はMaybe aであるため
                     (aの型の値を持たないので、aを決定する必要がない)
                 同様に空リストは任意の型引数を取るリストとして扱える
7.4 型引数
• 型引数の使いどころ
どんな型をそこに持ってきても変わらず
動作するようなデータ構造
Ex. Maybe, List, Map, Stack, Queue など


• データ型宣言時のルール
データ型宣言には型クラス制約をつけない
-- 順序型クラスの制約を持つ型を型引数に取るMaybe

data (Ord a) => Maybe' a = Nothing' | Just' a

             不必要に型引数を使いすぎると返って煩雑にしすぎてしまう
                     データに制約をつけず、関数の方に制約をつける
          (データにつけるとオプションが無い限りコンパイル時エラー)
7.5 インスタンスの自動導出
• 型クラスの自動導出
データ型の宣言 deriving (自動導出する型クラス)


• 自動導出可能な型クラス(P.28-32)
Eq(等価判定), Ord(順序付け),
Enum(列挙可能), Bounded(上限下限あり),
Show(文字列に変換可能),
Read(文字列から変換可能)
7.5 インスタンスの自動導出
• 自動導出全部入り
data Day = Monday | Tuesday | Wednesday |
 Thursday | Friday | Saturday | Sunday
 deriving
  (Eq, Ord, Show, Read, Bounded, Enum)


ghci> Monday == Monday    -- Eq
True
ghci> Friday < Sunday     -- Ord
True

                         書いた値で、最初に書いた値ほど小さい
7.5 インスタンスの自動導出
• 動作の確認
ghci> show Monday            -- Show
“Monday”
ghci> read “Monday” :: Day   -- Read
True

ghci> [minBound .. maxBound] :: [Day]
[Monday | Tuesday | Wednesday | Thursday |
 Friday | Saturday | Sunday]

                             最後の例はBoundedとEnumの複合
                  最小の要素(Bounded)と最大の要素(Bounded)を含む
                              Day型の値を列挙していく(Enum)
7.6 型シノニム
• 既存データ型に別の名前を与える
type String = [Char]
type IntMaybe = Maybe Int
type Pair a b = (a, b)
type MyStr = String
testStr :: MyStr -> String
testStr s = s

                   コンパイルエラー
ghci> Pair 1 2
ghci> testStr (“abc” :: [Char])

                                  別の名前を与えるだけの機能であり
                        値コンストラクタを作ってくれるわけではない
        別名であるので、同じものを指すのであれば関数の引数に引き渡せる
7.6 型シノニム
• 型引数を2つ取る型の例
data Either a b = Left a | Right b
 deriving (Eq, Ord, Read, Show)

ghci> :t Left True
Left True :: Either True b
ghci> :t Right ‘a’
Right ‘a’ :: Either a Char



                      Leftは後の型引数bを多相のまま残して失敗を表し
                     Rightは先の型引数aを多相のまま残して成功を表す
         Q. なぜLeftを失敗に使い、Rightを成功に使うのか?(Rightだから?)
7.6 型シノニム

• 失敗した時になぜ失敗したのかを返せる
on1to10 :: Int -> Either Ordering Int
on1to10 x
 | x < 1 = Left LT -- value less than [1,10]
 | x > 10 = Left GT -- value greater than [1,10]
 | otherwise = Right x -- value on [1,10]




                   整数が範囲内であるかどうかを判定する関数on1to10
                    範囲外である場合に、引数が小さいor大きいという
                        型情報Orderingの値を失敗値Leftと一緒に返す
7.7 再帰的なデータ構造
• フィールドに自分自身の型を持つデータ型
data List’ a = Empty | Cons a (List’ a)
  deriving (Show, Read, Eq, Ord)

ghci> Empty
Empty
ghci> 4 `Cons` (5 `Cons` Empty)
Cons 4 (Cons 5 Empty)
ghci> :t Cons
Cons :: a -> List' a -> List' a

             List’はEmpty、もしくはCons値コンストラクタで作成された値
             ConsコンストラクタはaとList’ aを取ってList’ aの値を作成する
7.7 再帰的なデータ構造
• イメージでつかもう
data List’ a = Empty | Cons a (List’ a)
  deriving (Show, Read, Eq, Ord)


 List’
            Empty
                       |       Cons a (List’ a)


                                           1 : 2 : 3 : []


1 `Cons` 2 `Cons` 3 `Cons`           Empty
7.7 再帰的なデータ構造
• 中置記号で書き直す              コロン(:)から始まる記号のみの値コ
                         ンストラクタは中置関数になる
infixr 5 :-:
data List’ a = Empty | a :-: (List’ a)
   deriving (Show, Read, Eq, Ord)

ghci> 1 :-: 2 :-: Empty
ghci> (1 :-: ( 2 :-: Empty))



            infixl or infixrで右結合か左結合かを指定する(省略すると右結合)
         また、結合性の優先順位を指定する(数字が大きいほど優先して結合)
                     省略した場合はinfixl 9が指定されていることと同じ
             右結合を指定しない場合は下のように括弧をつける必要がある
7.7 再帰的なデータ構造
• リストを連結する関数を実装
infixr 5 ^++
(^++) :: List' a -> List' a -> List' a
(^++) Empty ys = ys
(^++) (x :-: xs) ys = x :-: (xs ^++ ys)



                  記号だけで関数を実装すると、自動的に中置記法になる
                          関数の実装にパターンマッチを使用している
     パターンマッチとは値コンストラクタをマッチさせることに他ならない!
                               (Emptyも:-:も値コンストラクタである)
             Q. 組み込みのリストでは[]を値コンストラクタとして使えるが
                このように記号を値コンストラクタにできる実装はある?
7.7 再帰的なデータ構造
• 木構造(2分探索木)
data Tree a =
  EmptyTree | Node a (Tree a) (Tree a)
  deriving (Show)

Tree
        EmptyTree       Node a (Tree a) (Tree b)



 Nodeは値aと左の木、右の木を持つ
7.7 再帰的なデータ構造

Tree
       EmptyTree   Node a (Tree a) (Tree b)

                            P.139に描かれている木の例


                   5

         3                     7

   1           4        6             8
7.7 再帰的なデータ構造

• 木構造(2分[探索]木)
data Tree a =
  EmptyTree | Node a (Tree a) (Tree a)
  deriving (Show)




            この定義だけでは、ただの2分木を表現しているに過ぎない
       そのため、上記のデータ型では2分探索木では無いTreeも表現できる
          Q. 型引数に型クラス制約をつけないというルールはあったが、
     データ構造上の制約をデータ型の定義の段階で入れることはあるのか?
7.7 再帰的なデータ構造
• 2分探索木を作成するための関数を定義
singleton :: a -> Tree a
singleton x = Node x EmptyTree EmptyTree

treeInsert :: (Ord a) => a -> Tree a -> Tree a
treeInsert :: x EmptyTree = singleton x
treeInsert :: x (Node v left right)
  | x == v = Node v left right
  | x < v = Node v (treeInsert x left) right
  | x > v = Node v left (treeInsert x right)

                             木が空なら、新たなノードを作成する
木に値がある場合、挿入する値が小さければ左へ、値が大きければ右へ挿入する
7.7 再帰的なデータ構造

• 2分探索木に特定の値があるかを探索する関数
treeElem :: (Ord a) => a -> Tree a -> Bool
treeElem :: x EmptyTree = False
treeElem :: x (Node v left right)
  | x == v = True
  | x < v = treeElem x left
  | x > v = treeElem x right




               第2引数のTree aが2分探索木であれば正しい答えを返す
                       Q. このような時にInvalidな値を渡された場合
                            Haskellではどのように対処するのか?
7.7 再帰的なデータ構造

• 2分探索木の作成
let nums = [8,6,4,1,7,3,5]
let tree = foldr treeInsert EmptyTree nums

*Main> :t foldr
foldr :: (a -> b -> b) -> b -> [a] -> b

                       foldrにはa,bの2匹数を受け取りbを返す関数(第1引数)と
                                           その関数に与える初期値(第2引数)
                           および関数に順に与える値のリスト(第3引数)を渡す
                                ここでは、まずtreeInsert 5 EmptyTreeが行われ
                            その戻り値(Node 5 EmptyTree EmptyTree)に対して
                            treeInsert 3 (Node 5 EmptyTree EmptyTree) が行われ
                    ...と続いていき最終的にP.139の2分探索木を最終的に得る
7.8 型クラス中級講座

• WARNING!

この先に進む前に
型クラスという言葉に対して
手続き型言語にでてくる「クラス」については
とりあえず忘れて欲しいな!




                 型クラスは特定の振る舞いを表現するものであり、
             JavaやPythonのクラスではなくインタフェースのようなもの
        型クラスの振る舞いは、型クラス関数を定義することで得られる
7.8 型クラス中級講座

• Eq型クラスの実装               Eq型クラスの定義の始まり
                          a: Eqのインスタンスになる型を表す
class Eq a where
 (==) :: a -> a -> Bool
 (/=) :: a -> a -> Bool
                           Eq型クラスのインスタンスであれば
 x == y = not (x /= y)     使用できる関数 ( == と /= )
 x /= y = not (x == y)
   型クラス関数のデフォルト実装
   (省略可能)


                 ある型をEq型クラスのインスタンスにしようとする場合
                      定義されている全ての関数を実装する必要がある
              Eq型クラスの場合はデフォルト実装が相互再帰しているので
                              どちらか一方を書き換えるだけでよい
7.8 型クラス中級講座
• Eq型クラスのインスタンスの実装
data TrafficLight = Red | Yellow | Green
instance Eq TrafficLight where
  Red == Red = True
  Yellow == Yellow = True
  Green == Green = True
  _ == _ = False            Eq型クラスの関数(==)の実装

-- x /= y = not (x == y)    (パターンマッチを利用)



                    関数(/=)は関数(==)を用いて定義されているので
                   関数(==)の実装を上書きすることでEq型クラスで
                      必要とされる関数の実装を行うことができる
                                (型クラスの最小完全性定義)
7.8 型クラス中級講座
• 型クラスのサブクラス
class (Eq a) => Num a where
 ...

                    2つのインスタンス関係のイメージ

 Eq型クラスの
 インスタンス
                              Num型クラスの
                              インスタンス


                        型クラスNumのインスタンスとなる型は
                      型クラスEqのインスタンスである必要がある
7.8 型クラス中級講座
• 多層型(Maybe)のインスタンス

instance (Eq m) => Eq (Maybe m) where
  Just x == Just y = x == y
  Nothing == Nothing = True
  _ == _ = False

                      Eq型クラスのインスタンスである型mを
                      持つ(Maybe m)の具体型に対して
                      Eq型クラスのインスタンスを定義する
                      (これはmに対して==を使用しているため)



      逐一型ごとに(Maybe Int, Maybe Char, ...)インスタンスを実装せずとも
      型を単に変数と記述してインスタンスを実装することが許されている
7.8 型クラス中級講座
• 型クラスについての情報
ghci> :info Num
class Num a where
  (+) :: a -> a -> a
  (*) :: a -> a -> a
  (-) :: a -> a -> a
  negate :: a -> a
  abs :: a -> a
  signum :: a -> a
  fromInteger :: Integer -> a
       -- Defined in `GHC.Num'
instance Num Integer -- Defined in `GHC.Num'
instance Num Int -- Defined in `GHC.Num'
instance Num Float -- Defined in `GHC.Float'
instance Num Double -- Defined in `GHC.Float'


                            :info [型クラス名]で、型クラスの性質を示す関数と
                     実装されているインスタンス一覧を表示することができる
7.9 YesとNoの型クラス
• 型クラスを自作する
class YesNo a where
 yesno :: a -> Bool

• 自作の型クラスを独自実装する(例: Maybe)
instance (YesNo m) => YesNo (Maybe m) where
  yesno (Just x) = yesno x
  yesno _ = False

                       C言語やJavaScriptの条件判定がtrueとなる
          (ifの中に記述するとtrueと判断されるもの)を表現する型クラス
                        使用する時は型指定が必要なこともある
                      (yesno 0だけではIntと推論してくれなかった)
7.9 YesとNoの型クラス
• If式(っぽいもの)を自作する

yesnoIf :: (YesNo y) => y -> a -> a -> a
yesnoIf yesnoVal tValue fValue
 | yesno yesnoVal = tValue
 | otherwise = fValue




                                 Haskellでは遅延評価であるため
                     tValue, fValueの値が必要になるまで評価されない
                                     一方で正格評価な言語では
                     この関数が実行される段階でtValue, fValueともに
                               評価が終わっていなければならない
7.10 Functor型クラス
• 全体を写せる(map over)ものの型クラス

  class Functor something where
   fmap (a -> b) -> something a -> something b


       1, 2, 3, ..., 26
                                                       型クラス
  型クラス                    Int -> Char              something Char
something Int
                                        ‘A’, ‘B’, ‘C’, ..., ‘Z’

         ある型がFunctorであるならば、その型に対するfmapが提供されている
           fと書くと単なる関数のように見えたのでsomethingで書き直してある
7.10 Functor型クラス

• Maybe, List, TreeなどはFunctor型クラスのインスタンス

 instance Functor Maybe where
   fmap f (Just x) = Just (f x)
   fmap f Nothing = Nothing


class Eq a where             class Functor something where
 (==) :: a -> a -> Bool       fmap (a -> b) ->
 (/=) :: a -> a -> Bool         something a -> something b



                          Functor型クラスのインスタンスとして指定する型は
                           型を1つ取る型コンストラクタを持つ必要がある
                (Functorは具体型では無く、型コンストラクタを要求している)
7.10 Functor型クラス

• 1つの型コンストラクタを持てば良いのでEitherでもOK

instance Functor (Either a) where
 fmap f (Right rx) = Right $ f rx
 fmap f (Left lx) = Left lx       Either aのaは型変数
                                  任意のaに対してのインスタ
                                  ンスを実装
ghci> fmap (*2) (Right 10)
Right 20
ghci> fmap (*2) (Left “ABC”)
Left “ABC”

               fmapの第1匹数はRightの値の型bを別の型に変換する関数
                 Leftに使われる型aに対しては写像関数fの対象ではない
7.11 型を司るもの、種類
• :kコマンドで型の種類を知ることができる
ghci> :k Int
Int :: *
ghci> :k Maybe
Maybe :: * -> *
ghci> :k Maybe Int
Maybe Int :: *
ghci> :k Either String
Either String :: * -> *

                                       *は具体型 (Intなど)
       * -> *は具体型を1つ取って具体型を返す型コンストラクタ (Maybeなど)
     * -> * -> *は具体型を2つ取って具体型を返す型コンストラクタ (Eitherなど)
                              なお、部分適用を行うことも可能
演習問題1
• 木の最大の深さを求める関数を実装せよ。ただし、空の木
 の深さは0とし、P.139の木の深さを3とする

getMaxDepth :: Tree a -> Int
(以下を実装する)


• 2分探索木の中から最大の値を取得する関数を実装せよ

getMaxNode :: (Ord a) => Tree a -> Maybe a
(以下を実装する)


引数に渡されるTree aは正しい2分探索木であると
仮定してよい
演習問題2
• 型クラスMyStackを次のように定義する

class MyStack s where
 push :: a -> s a -> s a
 pop :: s a -> Maybe (a, s a)
 peek :: s a -> Maybe a


この時、標準で提供されるリストをMyStackのインスタンス
として定義せよ

instance MyStack [] where
  (以下を実装する)
演習問題1: 解答例

getMaxDepth :: Tree a -> Int
getMaxDepth EmptyTree = 0
getMaxDepth (Node _ left right) =
 1 + max (getMaxDepth left) (getMaxDepth right)


  左と右の木の深い方の木に、1を加えたものが自分の深さ


getMaxNode :: (Ord a) => Tree a -> Maybe a
getMaxNode EmptyTree = Nothing
getMaxNode (Node x _ EmptyTree) = Just x
getMaxNode (Node _ _ right) = getMaxNode right


2分探索木なので、最も右側にあるノードが最大の値を保持する
演習問題2: 解答例

instance MyStack [] where
  push x xs = x:xs
  pop [] = Nothing
  pop (x:xs) = Just (x, xs)
  peek [] = Nothing
  peek (x:_) = Just x


• push: 要素を先頭に追加したリストを返す
• pop: 要素があれば、先頭から取り出した値と先頭を取り除
 いたリストを返す

• peek: 要素があれば、先頭の値を返す
演習問題2: 動作例


ghci> let stack = foldr push [] [1,2,3,4,5]
ghci> stack
[1,2,3,4,5]
ghci> peek stack
Just 1
ghci> pop stack
Just (1,[2,3,4,5])
ghci> pop []
Nothing

Weitere ähnliche Inhalte

Was ist angesagt?

関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門Hideyuki Tanaka
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるHideyuki Tanaka
 
関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCamlHaruka Oikawa
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lensNaoki Aoyama
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたblackenedgold
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門Kimikazu Kato
 
(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義するblackenedgold
 
brainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusablebrainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusableroodni
 
C++のライブラリを簡単に眺めてみよう
C++のライブラリを簡単に眺めてみようC++のライブラリを簡単に眺めてみよう
C++のライブラリを簡単に眺めてみようHiro H.
 
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)Nozomu Kaneko
 
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キューYuto Takei
 
for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力imuyaoti
 
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Takashi J OZAKI
 
関数の最小値を求めることから機械学習へ
関数の最小値を求めることから機械学習へ関数の最小値を求めることから機械学習へ
関数の最小値を求めることから機械学習へHiro H.
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数Shinichi Kozake
 
Introduction to Categorical Programming (Revised)
Introduction to Categorical Programming (Revised)Introduction to Categorical Programming (Revised)
Introduction to Categorical Programming (Revised)Masahiro Sakai
 
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)Yoichi Nakayama
 
すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料Hiromasa Ohashi
 

Was ist angesagt? (20)

関数プログラミング入門
関数プログラミング入門関数プログラミング入門
関数プログラミング入門
 
C++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISるC++コミュニティーの中心でC++をDISる
C++コミュニティーの中心でC++をDISる
 
関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml関数型プログラミング入門 with OCaml
関数型プログラミング入門 with OCaml
 
Van laarhoven lens
Van laarhoven lensVan laarhoven lens
Van laarhoven lens
 
Real World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみたReal World OCamlを読んでLispと協調してみた
Real World OCamlを読んでLispと協調してみた
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門純粋関数型アルゴリズム入門
純粋関数型アルゴリズム入門
 
(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する(define)なしで再帰関数を定義する
(define)なしで再帰関数を定義する
 
brainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusablebrainfuckを吐く自作言語bf-reusable
brainfuckを吐く自作言語bf-reusable
 
C++のライブラリを簡単に眺めてみよう
C++のライブラリを簡単に眺めてみようC++のライブラリを簡単に眺めてみよう
C++のライブラリを簡単に眺めてみよう
 
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
すごいHaskell 第7章 型や型クラスを自分で作ろう(前編)
 
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
[Basic 3] 計算量 / 配列, 連結リスト / ハッシュ テーブル / スタック, キュー
 
for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力for関数を使った繰り返し処理によるヒストグラムの一括出力
for関数を使った繰り返し処理によるヒストグラムの一括出力
 
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
Deep Learningと他の分類器をRで比べてみよう in Japan.R 2014
 
実用Brainf*ckプログラミング
実用Brainf*ckプログラミング実用Brainf*ckプログラミング
実用Brainf*ckプログラミング
 
関数の最小値を求めることから機械学習へ
関数の最小値を求めることから機械学習へ関数の最小値を求めることから機械学習へ
関数の最小値を求めることから機械学習へ
 
たのしい高階関数
たのしい高階関数たのしい高階関数
たのしい高階関数
 
Introduction to Categorical Programming (Revised)
Introduction to Categorical Programming (Revised)Introduction to Categorical Programming (Revised)
Introduction to Categorical Programming (Revised)
 
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
すごいHaskell読書会 in 大阪 2週目 #5 第5章:高階関数 (2)
 
すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料すごいHaskell読書会 第六章 発表資料
すごいHaskell読書会 第六章 発表資料
 

Andere mochten auch

Haskell golf intro
Haskell golf introHaskell golf intro
Haskell golf intronotogawa
 
An engineer uses monads
An engineer uses monadsAn engineer uses monads
An engineer uses monadsKousuke Ruichi
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書くHideyuki Tanaka
 
20120830 DBリファクタリング読書会第三回
20120830 DBリファクタリング読書会第三回20120830 DBリファクタリング読書会第三回
20120830 DBリファクタリング読書会第三回都元ダイスケ Miyamoto
 
テスト自動化読書会 第3章 20150523
テスト自動化読書会 第3章 20150523テスト自動化読書会 第3章 20150523
テスト自動化読書会 第3章 20150523dnoguchi
 
Tapl 5
Tapl 5Tapl 5
Tapl 5rf0444
 
第4章 自動比較
第4章 自動比較第4章 自動比較
第4章 自動比較toku toku
 
システムテスト自動化標準ガイド第7章
システムテスト自動化標準ガイド第7章システムテスト自動化標準ガイド第7章
システムテスト自動化標準ガイド第7章nihon buson
 
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグアジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグDai FUJIHARA
 
WooCommerce & Apple TV
WooCommerce & Apple TVWooCommerce & Apple TV
WooCommerce & Apple TVMarko Heijnen
 
文芸的プログラミング
文芸的プログラミング文芸的プログラミング
文芸的プログラミングShoko Sasaki
 
システムテスト自動化標準ガイド 5章発表資料
システムテスト自動化標準ガイド 5章発表資料システムテスト自動化標準ガイド 5章発表資料
システムテスト自動化標準ガイド 5章発表資料Masatoshi Itoh
 
[デブサミ2015] スクラムならうまくいく? 〜グリーのネイティブゲーム作りの歴史をひもとく、 そして未来へ〜
[デブサミ2015] スクラムならうまくいく?〜グリーのネイティブゲーム作りの歴史をひもとく、そして未来へ〜[デブサミ2015] スクラムならうまくいく?〜グリーのネイティブゲーム作りの歴史をひもとく、そして未来へ〜
[デブサミ2015] スクラムならうまくいく? 〜グリーのネイティブゲーム作りの歴史をひもとく、 そして未来へ〜gree_tech
 
LeanCustomerDevelopment
LeanCustomerDevelopmentLeanCustomerDevelopment
LeanCustomerDevelopmentKouki Kawagoi
 
20150418 システムテスト自動化 第二章
20150418 システムテスト自動化 第二章20150418 システムテスト自動化 第二章
20150418 システムテスト自動化 第二章atsushi ishiji
 
TAPL勉強会 第1章 (2012-07-17)
TAPL勉強会 第1章 (2012-07-17)TAPL勉強会 第1章 (2012-07-17)
TAPL勉強会 第1章 (2012-07-17)none_toka
 
NaITE#15オープニング資料
NaITE#15オープニング資料NaITE#15オープニング資料
NaITE#15オープニング資料Akira Ikeda
 
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~健 渡会
 
システムテスト自動化標準ガイド 読書会 第8章
システムテスト自動化標準ガイド 読書会 第8章システムテスト自動化標準ガイド 読書会 第8章
システムテスト自動化標準ガイド 読書会 第8章mirer
 

Andere mochten auch (20)

Haskell Lecture 2
Haskell Lecture 2Haskell Lecture 2
Haskell Lecture 2
 
Haskell golf intro
Haskell golf introHaskell golf intro
Haskell golf intro
 
An engineer uses monads
An engineer uses monadsAn engineer uses monads
An engineer uses monads
 
IdrisでWebアプリを書く
IdrisでWebアプリを書くIdrisでWebアプリを書く
IdrisでWebアプリを書く
 
20120830 DBリファクタリング読書会第三回
20120830 DBリファクタリング読書会第三回20120830 DBリファクタリング読書会第三回
20120830 DBリファクタリング読書会第三回
 
テスト自動化読書会 第3章 20150523
テスト自動化読書会 第3章 20150523テスト自動化読書会 第3章 20150523
テスト自動化読書会 第3章 20150523
 
Tapl 5
Tapl 5Tapl 5
Tapl 5
 
第4章 自動比較
第4章 自動比較第4章 自動比較
第4章 自動比較
 
システムテスト自動化標準ガイド第7章
システムテスト自動化標準ガイド第7章システムテスト自動化標準ガイド第7章
システムテスト自動化標準ガイド第7章
 
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグアジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
アジャイルリーダーシップと組織改革 ~楽天のアジャイル開発というリアル~ エピローグ
 
WooCommerce & Apple TV
WooCommerce & Apple TVWooCommerce & Apple TV
WooCommerce & Apple TV
 
文芸的プログラミング
文芸的プログラミング文芸的プログラミング
文芸的プログラミング
 
システムテスト自動化標準ガイド 5章発表資料
システムテスト自動化標準ガイド 5章発表資料システムテスト自動化標準ガイド 5章発表資料
システムテスト自動化標準ガイド 5章発表資料
 
[デブサミ2015] スクラムならうまくいく? 〜グリーのネイティブゲーム作りの歴史をひもとく、 そして未来へ〜
[デブサミ2015] スクラムならうまくいく?〜グリーのネイティブゲーム作りの歴史をひもとく、そして未来へ〜[デブサミ2015] スクラムならうまくいく?〜グリーのネイティブゲーム作りの歴史をひもとく、そして未来へ〜
[デブサミ2015] スクラムならうまくいく? 〜グリーのネイティブゲーム作りの歴史をひもとく、 そして未来へ〜
 
LeanCustomerDevelopment
LeanCustomerDevelopmentLeanCustomerDevelopment
LeanCustomerDevelopment
 
20150418 システムテスト自動化 第二章
20150418 システムテスト自動化 第二章20150418 システムテスト自動化 第二章
20150418 システムテスト自動化 第二章
 
TAPL勉強会 第1章 (2012-07-17)
TAPL勉強会 第1章 (2012-07-17)TAPL勉強会 第1章 (2012-07-17)
TAPL勉強会 第1章 (2012-07-17)
 
NaITE#15オープニング資料
NaITE#15オープニング資料NaITE#15オープニング資料
NaITE#15オープニング資料
 
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
Stg2015 1c-1プレゼン資料 いまココにある請負アジャイル開発現場の実態 ~4年で4億弱売上20案件以上の実践経験から語る~
 
システムテスト自動化標準ガイド 読書会 第8章
システムテスト自動化標準ガイド 読書会 第8章システムテスト自動化標準ガイド 読書会 第8章
システムテスト自動化標準ガイド 読書会 第8章
 

Ähnlich wie  

すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)Suguru Hamazaki
 
Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章Prunus 1350
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)啓 小笠原
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜Hiromi Ishii
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2Masao Kato
 
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと 12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと Haruka Ozaki
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Ransui Iso
 
統計環境R_データ入出力編2016
統計環境R_データ入出力編2016統計環境R_データ入出力編2016
統計環境R_データ入出力編2016wada, kazumi
 
第1回R勉強会@東京
第1回R勉強会@東京第1回R勉強会@東京
第1回R勉強会@東京Yohei Sato
 
Rプログラミング02 データ入出力編
Rプログラミング02 データ入出力編Rプログラミング02 データ入出力編
Rプログラミング02 データ入出力編wada, kazumi
 
Scalaプログラミング・マニアックス
Scalaプログラミング・マニアックスScalaプログラミング・マニアックス
Scalaプログラミング・マニアックスTomoharu ASAMI
 
JavaScript経験者のためのGo言語入門
JavaScript経験者のためのGo言語入門JavaScript経験者のためのGo言語入門
JavaScript経験者のためのGo言語入門Shohei Arai
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Naoki Aoyama
 
2011年11月11日
2011年11月11日2011年11月11日
2011年11月11日nukaemon
 
Implicit Explicit Scala
Implicit Explicit ScalaImplicit Explicit Scala
Implicit Explicit ScalaKota Mizushima
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成Akineko Shimizu
 
Evolution Of Enumerator
Evolution Of EnumeratorEvolution Of Enumerator
Evolution Of EnumeratorAkinori Musha
 
Rプログラミング01 はじめの一歩
Rプログラミング01 はじめの一歩Rプログラミング01 はじめの一歩
Rプログラミング01 はじめの一歩wada, kazumi
 

Ähnlich wie   (20)

すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)すごいHaskell読書会 第7章 (前編)
すごいHaskell読書会 第7章 (前編)
 
Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章Rで学ぶデータマイニングI 第8章〜第13章
Rで学ぶデータマイニングI 第8章〜第13章
 
関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)関数型言語&形式的手法セミナー(3)
関数型言語&形式的手法セミナー(3)
 
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
How wonderful to be (statically) typed 〜型が付くってスバラシイ〜
 
たのしい関数型
たのしい関数型たのしい関数型
たのしい関数型
 
Thinking in Cats
Thinking in CatsThinking in Cats
Thinking in Cats
 
Clojure programming-chapter-2
Clojure programming-chapter-2Clojure programming-chapter-2
Clojure programming-chapter-2
 
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと 12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
12-11-30 Kashiwa.R #5 初めてのR Rを始める前に知っておきたい10のこと
 
Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3Lisp Tutorial for Pythonista : Day 3
Lisp Tutorial for Pythonista : Day 3
 
統計環境R_データ入出力編2016
統計環境R_データ入出力編2016統計環境R_データ入出力編2016
統計環境R_データ入出力編2016
 
第1回R勉強会@東京
第1回R勉強会@東京第1回R勉強会@東京
第1回R勉強会@東京
 
Rプログラミング02 データ入出力編
Rプログラミング02 データ入出力編Rプログラミング02 データ入出力編
Rプログラミング02 データ入出力編
 
Scalaプログラミング・マニアックス
Scalaプログラミング・マニアックスScalaプログラミング・マニアックス
Scalaプログラミング・マニアックス
 
JavaScript経験者のためのGo言語入門
JavaScript経験者のためのGo言語入門JavaScript経験者のためのGo言語入門
JavaScript経験者のためのGo言語入門
 
Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術Scala の関数型プログラミングを支える技術
Scala の関数型プログラミングを支える技術
 
2011年11月11日
2011年11月11日2011年11月11日
2011年11月11日
 
Implicit Explicit Scala
Implicit Explicit ScalaImplicit Explicit Scala
Implicit Explicit Scala
 
とあるFlashの自動生成
とあるFlashの自動生成とあるFlashの自動生成
とあるFlashの自動生成
 
Evolution Of Enumerator
Evolution Of EnumeratorEvolution Of Enumerator
Evolution Of Enumerator
 
Rプログラミング01 はじめの一歩
Rプログラミング01 はじめの一歩Rプログラミング01 はじめの一歩
Rプログラミング01 はじめの一歩
 

 

  • 1. 「すごいHaskellたのしく学ぼう!」第7章 型や型クラスを 自分で作ろう 第3回 スタートHaskell2 2012年8月19日 @a_hisame
  • 2. 自己紹介 • あひさめ(@a_hisame) • 社会人2年目 • 今のところはSIerさんのお仕事メイン • Haskell学習は3度目の正直 • プログラミング、アナログゲーム全般、料理・お酒など
  • 3. 7.1 データ型 • 様々なデータ型 • Bool, Int, Char, Maybe, ... etc • dataキーワードで新しいデータ型を定義 -- Bool型を定義 data Bool = False | True 新しいデータ型「Bool」を定義 このBool型はFalse、または、Trueの値を取り得る (これらは値コンストラクタでもある) データ型名、値コンストラクタは大文字で始まる必要がある
  • 4. 7.2 形づくる -- フィールドの必要ないデータ型 data Bool = False | True -- フィールドを持つデータ型 data Shape = Circle Float Float Float | Rectangle Float Float Float Float ghci > :t Rectangle Rectangle :: Float -> Float -> Float -> Float -> Shape Circle, Rectangleは値コンストラクタ その後に渡す値を持つ、定義したデータ型の値を返す関数
  • 5. 7.2 形づくる • 図形(Shape)の面積を求める関数を定義 area :: Shape -> Float area ( Circle _ _ r ) = pi * r ^ 2 area ( Rectangle x1 y1 x2 y2 ) = (abs $ x2-x1) * (abs $ y2 - y1) area関数はShape型を受け取り、その面積(Float)を返す関数 引数のShape型を受け取る部分でパターンマッチを行い 型ごとに適切な実装を行っている (この関数は任意のShape型の値を引数として受け取れる)
  • 6. 7.2 形づくる • ghci上で次のコードを実行する data Shape = Circle Float Float Float | Rectangle Float Float Float Float Circle 10 20 5 <interactive>:19:1: No instance for (Show Shape) arising from a use of `print' Possible fix: add an instance declaration for (Show Shape) In a stmt of an interactive GHCi command: print it Shapeというデータ型の値を文字列として表示する方法が分かりません (ghci上で実行した場合、その値の文字列表現を結果として表示する)
  • 7. 7.2 形づくる • Shape型の定義に次の一文を追加 data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving (Show) Circle 10 20 5 deriving (Show) をつけることで、 Shapeデータ型の各値を文字列でどのように表現するかを 自動的に実装してくれる(詳しくは後述)
  • 8. 7.2 形づくる • ところで・・・ data Shape = Circle Float Float Float | Rectangle Float Float Float Float deriving (Show) Circle 10 20 5 Circleの10, 20, 5というのは何を表している? Circle [中心のX座標] [中心のY座標] [円の半径] を想定 しているが、この順番を間違えてしまうかも。 Shapeというデータ型の値を文字列として表示する方法が分かりません (ghci上で実行した場合、その値の文字列表現を結果として表示する)
  • 9. 7.2 形づくる • Point型を定義 data Point = Point Float Float deriving (Show) data Shape = Circle Point Float | Rectangle Point Point deriving (Show) Circle (Point 10 20) 5 Circle [中心座標] [円の半径] ということを型で表現できる データ型を表現するために 新たなデータ型を定義して使用することができる
  • 10. 7.2 形づくる • 図形(Shape)の面積を求める関数を修正 area :: Shape -> Float area ( Circle _ r ) = pi * r ^ 2 area ( Rectangle (Point x1 y1) (Point x2 y2) ) = (abs $ x2-x1) * (abs $ y2 - y1) area関数はShape型を受け取り、その面積(Float)を返す関数(修正版) データ型の中のデータ型もパターンマッチの対象にできる。
  • 11. 7.2 形づくる • モジュールとしてエクスポート module Shapes ( Point(..), Shape(Circle, Rectangle), area, baseCircle ) where データ型、値コンストラクタ(関数)、関数のエクスポート -- 値コンストラクタをエクスポートしない場合 module Shapes (Point, Shape) where モジュールとしてデータ型、値コンストラクタを個別にエクスポートできる 値コンストラクタを提供せず、生成用の関数を提供することで 値コンストラクタを使ったパターンマッチはできなくなるが 既存のプログラムを壊さずに型の内部表現が変更可能
  • 12. 7.3 レコード構文 • 名前付きのフィールドを備えたデータ型の作成 data Person = Person { firstName :: String , lastName :: String , age :: Int , height :: Float , phoneNumber :: String , flavor :: String } deriving (Show) フィールド名 :: フィールドの型 作成したデータ型のフィールドに それぞれ名前を持たせたデータ型を作成できる
  • 13. 7.3 レコード構文 • 値の作成と自動生成される関数 -- フィールド名の関数(データ型 -> フィールド)を自動生成する ghci> :t flavor flavor :: Person -> String -- レコード型の値を生成する(カンマ区切りでフィールドに値を設定) ghci> let p = Person { firstName = “Buddy”, lastName = “Finklestein”, age = 43, height = 184.2, phoneNumber = “526-2928”, flavor = “Chocolate” } レコード型のパラメータを名前付きで全て指定する(順序は自由) モジュールで値コンストラクタの指定をしなくてもレコード型の値を生成できる Q. レコード型の値をエクスポートするときにそれを公開しないようにできる?
  • 14. 7.4 型引数 • 値コンストラクタと型コンストラクタ data Point = Point Float Float deriving (Show) data Maybe a = Nothing | Just a このaが型引数 ghci> Point 5 10 (型を与えることで使用する具体型が決定される) ghci> Point “x” “y” -- ERROR ghci> Just 10 -- (Num a) => Maybe a ghci> Just “string” -- Maybe [Char] 値コンストラクタ:値を受け取って新しい値(Ex. Point 5.0 10.0)を作る 型コンストラクタ:型を受け取って新しい型(Ex. Maybe Int)を作る (この例では単なるMaybeという型の値は存在できないが Maybe Intという型の値は存在できる)
  • 15. 7.4 型引数 • 様々な型を格納するデータ型が作れる data Maybe a = Nothing | Just a -- もしも型引数がなければ... data IntMaybe = INothing | IJust Int data StrMaybe = SNothing | SJust String ghci> Just 10 :: Maybe Int ghci> Just “string” :: Maybe String 異なるデータ型ごとにデータを作る必要がなくなる
  • 16. 7.4 型引数 • 多相的 functionA :: Maybe Int -> String functionB :: Maybe String -> String ghci> :t [] [] :: [a] -- ([] a)と意味は同じ ghci> :t (++) (++) :: [a] -> [a] -> [a] MaybeのNothingはfunctionA, functionBのどちらの引数としても扱える Nothingの型はMaybe aであるため (aの型の値を持たないので、aを決定する必要がない) 同様に空リストは任意の型引数を取るリストとして扱える
  • 17. 7.4 型引数 • 型引数の使いどころ どんな型をそこに持ってきても変わらず 動作するようなデータ構造 Ex. Maybe, List, Map, Stack, Queue など • データ型宣言時のルール データ型宣言には型クラス制約をつけない -- 順序型クラスの制約を持つ型を型引数に取るMaybe data (Ord a) => Maybe' a = Nothing' | Just' a 不必要に型引数を使いすぎると返って煩雑にしすぎてしまう データに制約をつけず、関数の方に制約をつける (データにつけるとオプションが無い限りコンパイル時エラー)
  • 18. 7.5 インスタンスの自動導出 • 型クラスの自動導出 データ型の宣言 deriving (自動導出する型クラス) • 自動導出可能な型クラス(P.28-32) Eq(等価判定), Ord(順序付け), Enum(列挙可能), Bounded(上限下限あり), Show(文字列に変換可能), Read(文字列から変換可能)
  • 19. 7.5 インスタンスの自動導出 • 自動導出全部入り data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday deriving (Eq, Ord, Show, Read, Bounded, Enum) ghci> Monday == Monday -- Eq True ghci> Friday < Sunday -- Ord True 書いた値で、最初に書いた値ほど小さい
  • 20. 7.5 インスタンスの自動導出 • 動作の確認 ghci> show Monday -- Show “Monday” ghci> read “Monday” :: Day -- Read True ghci> [minBound .. maxBound] :: [Day] [Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday] 最後の例はBoundedとEnumの複合 最小の要素(Bounded)と最大の要素(Bounded)を含む Day型の値を列挙していく(Enum)
  • 21. 7.6 型シノニム • 既存データ型に別の名前を与える type String = [Char] type IntMaybe = Maybe Int type Pair a b = (a, b) type MyStr = String testStr :: MyStr -> String testStr s = s コンパイルエラー ghci> Pair 1 2 ghci> testStr (“abc” :: [Char]) 別の名前を与えるだけの機能であり 値コンストラクタを作ってくれるわけではない 別名であるので、同じものを指すのであれば関数の引数に引き渡せる
  • 22. 7.6 型シノニム • 型引数を2つ取る型の例 data Either a b = Left a | Right b deriving (Eq, Ord, Read, Show) ghci> :t Left True Left True :: Either True b ghci> :t Right ‘a’ Right ‘a’ :: Either a Char Leftは後の型引数bを多相のまま残して失敗を表し Rightは先の型引数aを多相のまま残して成功を表す Q. なぜLeftを失敗に使い、Rightを成功に使うのか?(Rightだから?)
  • 23. 7.6 型シノニム • 失敗した時になぜ失敗したのかを返せる on1to10 :: Int -> Either Ordering Int on1to10 x | x < 1 = Left LT -- value less than [1,10] | x > 10 = Left GT -- value greater than [1,10] | otherwise = Right x -- value on [1,10] 整数が範囲内であるかどうかを判定する関数on1to10 範囲外である場合に、引数が小さいor大きいという 型情報Orderingの値を失敗値Leftと一緒に返す
  • 24. 7.7 再帰的なデータ構造 • フィールドに自分自身の型を持つデータ型 data List’ a = Empty | Cons a (List’ a) deriving (Show, Read, Eq, Ord) ghci> Empty Empty ghci> 4 `Cons` (5 `Cons` Empty) Cons 4 (Cons 5 Empty) ghci> :t Cons Cons :: a -> List' a -> List' a List’はEmpty、もしくはCons値コンストラクタで作成された値 ConsコンストラクタはaとList’ aを取ってList’ aの値を作成する
  • 25. 7.7 再帰的なデータ構造 • イメージでつかもう data List’ a = Empty | Cons a (List’ a) deriving (Show, Read, Eq, Ord) List’ Empty | Cons a (List’ a) 1 : 2 : 3 : [] 1 `Cons` 2 `Cons` 3 `Cons` Empty
  • 26. 7.7 再帰的なデータ構造 • 中置記号で書き直す コロン(:)から始まる記号のみの値コ ンストラクタは中置関数になる infixr 5 :-: data List’ a = Empty | a :-: (List’ a) deriving (Show, Read, Eq, Ord) ghci> 1 :-: 2 :-: Empty ghci> (1 :-: ( 2 :-: Empty)) infixl or infixrで右結合か左結合かを指定する(省略すると右結合) また、結合性の優先順位を指定する(数字が大きいほど優先して結合) 省略した場合はinfixl 9が指定されていることと同じ 右結合を指定しない場合は下のように括弧をつける必要がある
  • 27. 7.7 再帰的なデータ構造 • リストを連結する関数を実装 infixr 5 ^++ (^++) :: List' a -> List' a -> List' a (^++) Empty ys = ys (^++) (x :-: xs) ys = x :-: (xs ^++ ys) 記号だけで関数を実装すると、自動的に中置記法になる 関数の実装にパターンマッチを使用している パターンマッチとは値コンストラクタをマッチさせることに他ならない! (Emptyも:-:も値コンストラクタである) Q. 組み込みのリストでは[]を値コンストラクタとして使えるが このように記号を値コンストラクタにできる実装はある?
  • 28. 7.7 再帰的なデータ構造 • 木構造(2分探索木) data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show) Tree EmptyTree Node a (Tree a) (Tree b) Nodeは値aと左の木、右の木を持つ
  • 29. 7.7 再帰的なデータ構造 Tree EmptyTree Node a (Tree a) (Tree b) P.139に描かれている木の例 5 3 7 1 4 6 8
  • 30. 7.7 再帰的なデータ構造 • 木構造(2分[探索]木) data Tree a = EmptyTree | Node a (Tree a) (Tree a) deriving (Show) この定義だけでは、ただの2分木を表現しているに過ぎない そのため、上記のデータ型では2分探索木では無いTreeも表現できる Q. 型引数に型クラス制約をつけないというルールはあったが、 データ構造上の制約をデータ型の定義の段階で入れることはあるのか?
  • 31. 7.7 再帰的なデータ構造 • 2分探索木を作成するための関数を定義 singleton :: a -> Tree a singleton x = Node x EmptyTree EmptyTree treeInsert :: (Ord a) => a -> Tree a -> Tree a treeInsert :: x EmptyTree = singleton x treeInsert :: x (Node v left right) | x == v = Node v left right | x < v = Node v (treeInsert x left) right | x > v = Node v left (treeInsert x right) 木が空なら、新たなノードを作成する 木に値がある場合、挿入する値が小さければ左へ、値が大きければ右へ挿入する
  • 32. 7.7 再帰的なデータ構造 • 2分探索木に特定の値があるかを探索する関数 treeElem :: (Ord a) => a -> Tree a -> Bool treeElem :: x EmptyTree = False treeElem :: x (Node v left right) | x == v = True | x < v = treeElem x left | x > v = treeElem x right 第2引数のTree aが2分探索木であれば正しい答えを返す Q. このような時にInvalidな値を渡された場合 Haskellではどのように対処するのか?
  • 33. 7.7 再帰的なデータ構造 • 2分探索木の作成 let nums = [8,6,4,1,7,3,5] let tree = foldr treeInsert EmptyTree nums *Main> :t foldr foldr :: (a -> b -> b) -> b -> [a] -> b foldrにはa,bの2匹数を受け取りbを返す関数(第1引数)と その関数に与える初期値(第2引数) および関数に順に与える値のリスト(第3引数)を渡す ここでは、まずtreeInsert 5 EmptyTreeが行われ その戻り値(Node 5 EmptyTree EmptyTree)に対して treeInsert 3 (Node 5 EmptyTree EmptyTree) が行われ ...と続いていき最終的にP.139の2分探索木を最終的に得る
  • 34. 7.8 型クラス中級講座 • WARNING! この先に進む前に 型クラスという言葉に対して 手続き型言語にでてくる「クラス」については とりあえず忘れて欲しいな! 型クラスは特定の振る舞いを表現するものであり、 JavaやPythonのクラスではなくインタフェースのようなもの 型クラスの振る舞いは、型クラス関数を定義することで得られる
  • 35. 7.8 型クラス中級講座 • Eq型クラスの実装 Eq型クラスの定義の始まり a: Eqのインスタンスになる型を表す class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool Eq型クラスのインスタンスであれば x == y = not (x /= y) 使用できる関数 ( == と /= ) x /= y = not (x == y) 型クラス関数のデフォルト実装 (省略可能) ある型をEq型クラスのインスタンスにしようとする場合 定義されている全ての関数を実装する必要がある Eq型クラスの場合はデフォルト実装が相互再帰しているので どちらか一方を書き換えるだけでよい
  • 36. 7.8 型クラス中級講座 • Eq型クラスのインスタンスの実装 data TrafficLight = Red | Yellow | Green instance Eq TrafficLight where Red == Red = True Yellow == Yellow = True Green == Green = True _ == _ = False Eq型クラスの関数(==)の実装 -- x /= y = not (x == y) (パターンマッチを利用) 関数(/=)は関数(==)を用いて定義されているので 関数(==)の実装を上書きすることでEq型クラスで 必要とされる関数の実装を行うことができる (型クラスの最小完全性定義)
  • 37. 7.8 型クラス中級講座 • 型クラスのサブクラス class (Eq a) => Num a where ... 2つのインスタンス関係のイメージ Eq型クラスの インスタンス Num型クラスの インスタンス 型クラスNumのインスタンスとなる型は 型クラスEqのインスタンスである必要がある
  • 38. 7.8 型クラス中級講座 • 多層型(Maybe)のインスタンス instance (Eq m) => Eq (Maybe m) where Just x == Just y = x == y Nothing == Nothing = True _ == _ = False Eq型クラスのインスタンスである型mを 持つ(Maybe m)の具体型に対して Eq型クラスのインスタンスを定義する (これはmに対して==を使用しているため) 逐一型ごとに(Maybe Int, Maybe Char, ...)インスタンスを実装せずとも 型を単に変数と記述してインスタンスを実装することが許されている
  • 39. 7.8 型クラス中級講座 • 型クラスについての情報 ghci> :info Num class Num a where (+) :: a -> a -> a (*) :: a -> a -> a (-) :: a -> a -> a negate :: a -> a abs :: a -> a signum :: a -> a fromInteger :: Integer -> a -- Defined in `GHC.Num' instance Num Integer -- Defined in `GHC.Num' instance Num Int -- Defined in `GHC.Num' instance Num Float -- Defined in `GHC.Float' instance Num Double -- Defined in `GHC.Float' :info [型クラス名]で、型クラスの性質を示す関数と 実装されているインスタンス一覧を表示することができる
  • 40. 7.9 YesとNoの型クラス • 型クラスを自作する class YesNo a where yesno :: a -> Bool • 自作の型クラスを独自実装する(例: Maybe) instance (YesNo m) => YesNo (Maybe m) where yesno (Just x) = yesno x yesno _ = False C言語やJavaScriptの条件判定がtrueとなる (ifの中に記述するとtrueと判断されるもの)を表現する型クラス 使用する時は型指定が必要なこともある (yesno 0だけではIntと推論してくれなかった)
  • 41. 7.9 YesとNoの型クラス • If式(っぽいもの)を自作する yesnoIf :: (YesNo y) => y -> a -> a -> a yesnoIf yesnoVal tValue fValue | yesno yesnoVal = tValue | otherwise = fValue Haskellでは遅延評価であるため tValue, fValueの値が必要になるまで評価されない 一方で正格評価な言語では この関数が実行される段階でtValue, fValueともに 評価が終わっていなければならない
  • 42. 7.10 Functor型クラス • 全体を写せる(map over)ものの型クラス class Functor something where fmap (a -> b) -> something a -> something b 1, 2, 3, ..., 26 型クラス 型クラス Int -> Char something Char something Int ‘A’, ‘B’, ‘C’, ..., ‘Z’ ある型がFunctorであるならば、その型に対するfmapが提供されている fと書くと単なる関数のように見えたのでsomethingで書き直してある
  • 43. 7.10 Functor型クラス • Maybe, List, TreeなどはFunctor型クラスのインスタンス instance Functor Maybe where fmap f (Just x) = Just (f x) fmap f Nothing = Nothing class Eq a where class Functor something where (==) :: a -> a -> Bool fmap (a -> b) -> (/=) :: a -> a -> Bool something a -> something b Functor型クラスのインスタンスとして指定する型は 型を1つ取る型コンストラクタを持つ必要がある (Functorは具体型では無く、型コンストラクタを要求している)
  • 44. 7.10 Functor型クラス • 1つの型コンストラクタを持てば良いのでEitherでもOK instance Functor (Either a) where fmap f (Right rx) = Right $ f rx fmap f (Left lx) = Left lx Either aのaは型変数 任意のaに対してのインスタ ンスを実装 ghci> fmap (*2) (Right 10) Right 20 ghci> fmap (*2) (Left “ABC”) Left “ABC” fmapの第1匹数はRightの値の型bを別の型に変換する関数 Leftに使われる型aに対しては写像関数fの対象ではない
  • 45. 7.11 型を司るもの、種類 • :kコマンドで型の種類を知ることができる ghci> :k Int Int :: * ghci> :k Maybe Maybe :: * -> * ghci> :k Maybe Int Maybe Int :: * ghci> :k Either String Either String :: * -> * *は具体型 (Intなど) * -> *は具体型を1つ取って具体型を返す型コンストラクタ (Maybeなど) * -> * -> *は具体型を2つ取って具体型を返す型コンストラクタ (Eitherなど) なお、部分適用を行うことも可能
  • 46. 演習問題1 • 木の最大の深さを求める関数を実装せよ。ただし、空の木 の深さは0とし、P.139の木の深さを3とする getMaxDepth :: Tree a -> Int (以下を実装する) • 2分探索木の中から最大の値を取得する関数を実装せよ getMaxNode :: (Ord a) => Tree a -> Maybe a (以下を実装する) 引数に渡されるTree aは正しい2分探索木であると 仮定してよい
  • 47. 演習問題2 • 型クラスMyStackを次のように定義する class MyStack s where push :: a -> s a -> s a pop :: s a -> Maybe (a, s a) peek :: s a -> Maybe a この時、標準で提供されるリストをMyStackのインスタンス として定義せよ instance MyStack [] where (以下を実装する)
  • 48. 演習問題1: 解答例 getMaxDepth :: Tree a -> Int getMaxDepth EmptyTree = 0 getMaxDepth (Node _ left right) = 1 + max (getMaxDepth left) (getMaxDepth right) 左と右の木の深い方の木に、1を加えたものが自分の深さ getMaxNode :: (Ord a) => Tree a -> Maybe a getMaxNode EmptyTree = Nothing getMaxNode (Node x _ EmptyTree) = Just x getMaxNode (Node _ _ right) = getMaxNode right 2分探索木なので、最も右側にあるノードが最大の値を保持する
  • 49. 演習問題2: 解答例 instance MyStack [] where push x xs = x:xs pop [] = Nothing pop (x:xs) = Just (x, xs) peek [] = Nothing peek (x:_) = Just x • push: 要素を先頭に追加したリストを返す • pop: 要素があれば、先頭から取り出した値と先頭を取り除 いたリストを返す • peek: 要素があれば、先頭の値を返す
  • 50. 演習問題2: 動作例 ghci> let stack = foldr push [] [1,2,3,4,5] ghci> stack [1,2,3,4,5] ghci> peek stack Just 1 ghci> pop stack Just (1,[2,3,4,5]) ghci> pop [] Nothing

Hinweis der Redaktion

  1. \n
  2. \n
  3. \n
  4. \n
  5. \n
  6. \n
  7. \n
  8. \n
  9. \n
  10. \n
  11. \n
  12. \n
  13. \n
  14. \n
  15. \n
  16. \n
  17. \n
  18. \n
  19. \n
  20. \n
  21. \n
  22. \n
  23. \n
  24. \n
  25. \n
  26. \n
  27. \n
  28. \n
  29. \n
  30. \n
  31. \n
  32. \n
  33. \n
  34. \n
  35. \n
  36. \n
  37. \n
  38. \n
  39. \n
  40. \n
  41. \n
  42. \n
  43. \n
  44. \n
  45. \n
  46. \n
  47. \n
  48. \n
  49. \n
  50. \n