人気ブログランキング |

RWH の読み方(48) 第6章

Real World Haskell 第6章 Using Typeclasses

Relaxing Some Restirctions on Typeclasses

Haskell 98 report のタイプクラスのインスタンスについての文法は実用的なプログラムには使いづらい。GHC ではこれらの制限を緩和するための言語拡張が用意されている。

タイプクラスのインスタンスにリストを使う場合、Haskell 98 では [a] のように要素が必ずタイプ変数でなければならない。したがって [Char] のようなインスタンスは文法エラーになる。[Char] (String) のような頻繁に使われるデータ型がタイプクラスのインスタンスにできないのは不便なので、GHC では言語拡張 TypeSynonymInstances が用意されている。

次のプログラムはコンパイルに失敗するが、

class Foo a where
  foo :: a -> a

instance Foo String where
  foo = id

実行例:

Prelude> :l classtest.hs
[1 of 1] Compiling Main             ( classtest.hs, interpreted )

classtest.hs:4:0:
    Illegal instance declaration for `Foo String'
        (All instance types must be of the form (T t1 ... tn)
         where T is not a synonym.
         Use -XTypeSynonymInstances if you want to disable this.)
    In the instance declaration for `Foo String'
Failed, modules loaded: none.

次のようにソースの冒頭の pragma で TypeSynonymInstances 言語拡張を指定するとコンパルも実行もできるようになる。

{-# LANGUAGE TypeSynonymInstances #-}

class Foo a where
  foo :: a -> a

instance Foo String where
  foo = id

実行例:

Prelude> :l classtest.hs
[1 of 1] Compiling Main             ( classtest.hs, interpreted )
Ok, modules loaded: Main.
*Main> foo "hello"
"hello"

このセクションでは他に OverlappingInstances 言語拡張についても述べているが、OverlappingInstances 言語拡張については前回の記事で紹介している。

How Does Show Work for Strings?

The OverlappingInstances 言語拡張のない Haskell 98 で文字列と整数のリストでは show 関数を使った文字列への変換で異なる出力になるようにするトリックについて解説してあるが、パスする。

How to Give a Type a New Identity
Differences Between Data and NewType Declalations
Summary: The Three Ways of Naming Types

Haskell でユーザ定義の型を定義するのに、data キーワードを使う場合、type キーワードを使う場合、newType キーワードを使う場合の3つの方法がある。

data キーワードを使ってユーザ定義型を作る方法は既に前章で記述されているのでここでは説明がない。

type キーワードは、
type String = [Char]
のように既存のデータ型の synonym (同義語)を指定するだけだから、特に詳しい説明はなくても理解できる。

newType キーワードは用途が制限された data キーワードのように働く。その制限とは、newType キーワードで定義できるデータ型は、一つだけのデータ・コンストラクタしか定義できないことだ、さらにそのデータ・コンストラクタは、フィールドの値として一つの値しかとることができない。newType で定義できるデータ型の例は、
newType Okay = ExactlyOne Int
だ。たった一つのデータ・コンストラクタ ExactlyOne とそのたったひとつのフィールド Int の形式を必ず取る必要がある。

このような不便な型宣言がなぜ必要かというと、それは newType で定義されたデータ型の実装は、data で定義されたデータ型の実装よりはるかに軽量になるからだ。

上に示した3つのセクションを使って、newType の特徴が詳しく調べられているが、実装の話になるのでスキップする。
by tnomura9 | 2012-05-27 19:57 | Haskell | Comments(0)
<< DANCEROID 名作選 RWH の読み方(47) 第6章 >>