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 型もなくなるので考える必要がなくなる?