いものやま。

雑多な知識の寄せ集め

GHCの使い方を調べてみた。(その7)

昨日はGHCiでの複数行の入力と、オフサイドルールについて説明した。

今日は、GHCiでの型などの宣言と、型や識別子、モジュールの調査について。

GHCiでの型などの宣言

GHCiでは、普通のHaskellソースコードと同じように、型や型クラスを宣言したり、型クラスのインスタンスを宣言することが出来る。

例えば、二分木を表すTree aという型を宣言してみると、以下のようになる:

Prelude> :{
Prelude| data Tree a = Leaf { element :: a }
Prelude|             | Fork { element :: a
Prelude|                    , left :: Tree a
Prelude|                    , right :: Tree a
Prelude|                    }
Prelude|             deriving (Show)
Prelude| :}
Prelude> :{
Prelude| let tree =
Prelude|       Fork { element = 1
Prelude|            , left = Fork { element = 2
Prelude|                          , left = Leaf { element = 3 }
Prelude|                          , right = Leaf { element = 4 }
Prelude|                          }
Prelude|            , right = Leaf { element = 5 }
Prelude|            }
Prelude| :}
Prelude> tree
Fork {element = 1, left = Fork {element = 2, left = Leaf {element = 3}, right = Leaf {element = 4}}, right = Leaf {element = 5}}
Prelude> 

型や識別子、モジュールの調査

GHCiでは、式の型や識別子の情報、そして、モジュールの情報を見ることが出来る。

まず、式の型を見る方法。
これには、:typeコマンド(省略形は:t)を使う。

Prelude> :t 1
1 :: Num a => a
Prelude> :t "Hi!"
"Hi!" :: [Char]
Prelude> :t [1..]
[1..] :: (Enum t, Num t) => [t]
Prelude> :t 1 + 2
1 + 2 :: Num a => a
Prelude> :t show
show :: Show a => a -> String
Prelude> :t (+)
(+) :: Num a => a -> a -> a
Prelude> :t Fork
Fork :: a -> Tree a -> Tree a -> Tree a
Prelude> :t map (+2)
map (+2) :: Num b => [b] -> [b]
Prelude> 

なお、演算子については、括弧で囲って関数にしないとダメ。

次に、識別子の情報を見る方法。
これには、:infoコマンド(省略形は:i)を使う。

Prelude> let a = 1
Prelude> :i a
a :: Num a => a         -- Defined at <interactive>:74:5
Prelude> let str = "hello"
Prelude> :i str
str :: [Char]   -- Defined at <interactive>:75:5
Prelude> let f = \x -> x * x
Prelude> :i f
f :: Num a => a -> a    -- Defined at <interactive>:78:5
Prelude> :i Tree
data Tree a
  = Leaf {element :: a}
  | Fork {element :: a, left :: Tree a, right :: Tree a}
        -- Defined at <interactive>:18:1
instance Show a => Show (Tree a) -- Defined at <interactive>:23:23
Prelude> :i Fork
data Tree a = ... | Fork {...}  -- Defined at <interactive>:19:15
Prelude> :i (+)
class Num a where
  (+) :: a -> a -> a
  ...
        -- Defined in ‘GHC.Num’
infixl 6 +
Prelude> :i 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 Word -- 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’
Prelude> 

最後に、モジュールの情報を見る方法。
これには、:browseコマンドを使う。

Prelude> :browse Data.Maybe
Data.Maybe.catMaybes :: [Maybe a] -> [a]
Data.Maybe.fromJust :: Maybe a -> a
Data.Maybe.fromMaybe :: a -> Maybe a -> a
Data.Maybe.isJust :: Maybe a -> Bool
Data.Maybe.isNothing :: Maybe a -> Bool
Data.Maybe.listToMaybe :: [a] -> Maybe a
Data.Maybe.mapMaybe :: (a -> Maybe b) -> [a] -> [b]
maybe :: b -> (a -> b) -> Maybe a -> b
Data.Maybe.maybeToList :: Maybe a -> [a]
data Maybe a = Nothing | Just a
Prelude> 

なお、:browse!コマンドを使うことも出来て、そうした場合、値コンストラクタも個別に表示され、また、グループ分けして表示される。

Prelude> :browse! Data.Maybe
-- not currently imported
Data.Maybe.catMaybes :: [Maybe a] -> [a]
Data.Maybe.fromJust :: Maybe a -> a
Data.Maybe.fromMaybe :: a -> Maybe a -> a
Data.Maybe.isJust :: Maybe a -> Bool
Data.Maybe.isNothing :: Maybe a -> Bool
Data.Maybe.listToMaybe :: [a] -> Maybe a
Data.Maybe.mapMaybe :: (a -> Maybe b) -> [a] -> [b]
Data.Maybe.maybeToList :: Maybe a -> [a]
-- imported via Prelude
maybe :: b -> (a -> b) -> Maybe a -> b
Just :: a -> Maybe a
data Maybe a = Nothing | Just a
Nothing :: Maybe a
Prelude> 

今日はここまで!