Haskellの言語拡張たち
前回、なんか拡張を沢山使っていたが、おまじないのままなのもそろそろまずい感じなので、とりあえず調べてみた。
今回調べた拡張
- 型系
- GADTs
- ScopedTypeVariables
- EmptyDataDecls
- TypeFamilies
- 型クラス系
- MultiParamTypeClasses
- TypeSynonymInstances
- FlexibleInstances
- FlexibleContexts
- パターン系
- BangPatterns
- PatternGuards
- ViewPatterns
- 文字列系
- OverloadedStrings
- TemplateHaskell系
- TemplateHaskell
- QuasiQuotes
- import系
- ImplicitPrelude
- PackageImports
- 他言語系
- CPP
- ForeignFunctionInterface
設定方法
hsファイルの上の方に、
{-# LANGUAGE 〜 #-}
な感じで書くか、実行時に
$ ghc -X〜 ... $ ghci -X〜 ... $ runhaskell -X〜 ...
な感じで指定する。
無効にする場合は、No〜 を指定する。
調べてるときに使った GHC は 7.0.4 。
型系
GADTs
代数的データ型のもつ型変数に対して、型を限定した型構築子が書ける。
{-# LANGUAGE GADTs #-} -- GADTs 拡張が必要 data List a where INil :: List Int CNil :: List Char Cons :: a -> List a -> List a
ScopedTypeVariables
スコープを持つ明示的な型変数 (forall) を書ける。
-- x と y の型が違うのでエラーになる myId :: a -> a myId x = y where y :: a y = x
↓
{-# LANGUAGE ScopedTypeVariables #-} -- ScopedTypeVariables 拡張が必要 myId :: forall a. a -> a myId x = y where y :: a y = x
EmptyDataDecls
構築子のないデータ型の宣言を書ける。
{-# LANGUAGE EmptyDataDecls #-} -- EmptyDataDecls 拡張が必要 data EmpData data EmpDataF a
何も指定しなくても通ったので、デフォルトで有効のよう。
試しに NoEmptyDataDecls を指定したら、コンパイラに EmptyDataDecls を指定しろといわれた。
TypeFamilies
型族やデータ族が書ける。
{-# LANGUAGE TypeFamilies #-} -- 型族 -- TypeFamilies 拡張が必要 type family TypeConv a :: * type instance TypeConv EmpData = Int type instance TypeConv (EmpDataF a) = a -- データ族 -- TypeFamilies 拡張が必要 data family MyDF a data instance MyDF Int = MyDF1 Int | MyDF2 Int Int newtype instance MyDF EmpData = MyDF3 Bool newtype instance MyDF (EmpDataF a) = MyDF4 a
型クラス系
MultiParamTypeClasses
型パラメータを複数持つ型クラスが書ける。
{-# LANGUAGE MultiParamTypeClasses #-} -- MultiParamTypeClasses 拡張が必要 class Set s a where empty :: s a insert :: a -> s a -> s a member :: a -> s a -> Bool
TypeSynonymInstances
型シノニム (typeで宣言した型) に対して、インスタンス宣言が書ける。
{-# LANGUAGE TypeSynonymInstances #-} class CHoge a where hoge :: a -> a type SHoge = String -- TypeSynonymInstances 拡張が必要 instance CHoge SHoge where hoge = id
FlexibleInstances
型引数を持つ型に、特定の型を与えたものに対して、インスタンス宣言が書ける。
{-# LANGUAGE FlexibleInstances #-} class CHoge a where hoge :: a -> a -- FlexibleInstances 拡張が必要 instance CHoge (Maybe Int) where hoge _ = Nothing
FlexibleContexts
型パラメータを複数持つ型クラス制約が書ける。
{-# LANGUAGE MultiParamTypeClasses, FlexibleContexts #-} -- MultiParamTypeClasses 拡張が必要 class CCHoge a b where choge :: a -> b -- FlexibleContexts 拡張が必要 ihoge :: (CCHoge a Int) => a -> Int ihoge _ = 0
パターン系
BangPatterns
!(パターン) で、束縛時にそのパターンを正格評価する。
{-# LANGUAGE BangPatterns #-} -- BangPatterns 拡張が必要 myseq :: a -> b -> b myseq !x y = y
PatternGuards
パターンを含むガードが書ける。
{-# LANGUAGE PatternGuards #-} -- PatternGuards 拡張が必要 justOddOrElse :: Maybe Int -> Int -> Int justOddOrElse x y | Just a <- x, odd a = a | otherwise = y
これもデフォルトで有効のよう。
ViewPatterns
パターンの中で関数を呼んで、その結果に対してマッチするパターンマッチ (関数 -> パターン) が書ける。
{-# LANGUAGE ViewPatterns #-} import Control.Monad (mfilter) -- ViewPatternt 拡張が必要 justOddOrElse :: Maybe Int -> Int -> Int justOddOrElse (mfilter odd -> Just a) _ = a justOddOrElse _ b = b
文字列系
OverloadedStrings
文字列リテラルの型を、Stringではなく、(IsString a) => a にする。
{-# LANGUAGE OverloadedStrings #-} import Data.ByteString (ByteString) import Data.ByteString.Char8 () -- for IsString ByteString -- OverloadedStrings 拡張が必要 hogebstr :: ByteString hogebstr = "hoge"
TemplateHaskell系
TemplateHaskell
TemplateHaskell の構文が使える。
コンパイル時メタプログラミングとかできるようになる。
QuasiQuotes
準クォート ([〜| 〜 |]) が使える。
Yesod の [persist| 〜 |] とか [hamlet| 〜 |] とか。
import系
ImplicitPrelude
Prelude を暗黙的にインポートする。
デフォルトで有効。
NoImplicitPrelude を指定することで、暗黙的に Prelude が import されないようにできる。
PackageImports
パッケージ名で修飾したimport宣言 (import "(パッケージ名)" ~) を書ける。
他言語系
ForeignFunctionInterface
他言語関数インタフェース (FFI) を有効にする。
デフォルトで有効らしい。