ghci で module で定義されている識別子の表示 と その他

:browse で指定したモジュールに定義されている識別子を表示する。Char モジュールで試してみる。

Prelude> :browse Char
data Char = GHC.Types.C# GHC.Prim.Char#
type String = [Char]
chr :: Int -> Char
digitToInt :: Char -> Int
intToDigit :: Int -> Char
isAlpha :: Char -> Bool
isAlphaNum :: Char -> Bool
isAscii :: Char -> Bool
isControl :: Char -> Bool
isDigit :: Char -> Bool
isHexDigit :: Char -> Bool
isLatin1 :: Char -> Bool
isLower :: Char -> Bool
isOctDigit :: Char -> Bool
isPrint :: Char -> Bool
isSpace :: Char -> Bool
isUpper :: Char -> Bool
lexLitChar :: ReadS String
ord :: Char -> Int
readLitChar :: ReadS Char
showLitChar :: Char -> ShowS
toLower :: Char -> Char
toUpper :: Char -> Char

適当に選んで Haskell でわざわざ実装してみようと思う。

isAscii

is〜系の関数が色々あるので、その中から一つ選んでみた。

import Char

myIsAscii :: Char -> Bool
myIsAscii a = code >= 0x00 && code <= 0x7f
  where code = ord a

Char モジュールの関数の ord を使っている。このコードはこのままだと、Char モジュールが使えなくなったときに破綻してしまうではないかっ*1

ord

そういうわけで、ord を実装してみる。

myOrd :: Char -> Int
myOrd a = ...

...どうやってやるんだ?わかりません...orz。ord は orz と似てるねと、どうでもいいことを書いてみたり。
C 言語だったら簡単なのに。簡単っていうか始めっから数値だし。

isAscii again

そんなわけで、ord を使わずやってみた。

myIsAscii :: Char -> Bool
myIsAscii a = (compare a '\x00' /= LT) && (compare a '\x7f' /= GT)

compare なんて関数あるんだね。返り値が特殊な感じ。LT, GT, EQ のどれかが返る。LE, GE はないのかなと思ったが、比較してるんだからないのは当然か、と気付くまで時間が掛かった。
not equal は != ではなく /= なんだ。≠と似てる?


って、ここまで書いてやっと気付いたけど、こうすればごちゃごちゃ考えなくてよかったじゃん。

myIsAscii a = a >= '\x00' &&  a <= '\x7f'
toUpper
import Char
myToUpper :: Char -> Char
myToUpper c
  | isLower c = chr $ ord c - 0x20
  | otherwise = c

おまけ程度。

*1:でも、Char モジュールがなくなれば Char 型もなくなるので考える必要がなくなる?