| ホーム > Haskell | 記事の検索 | サイト検索 | 更新情報 |
| プロフィール | 記事一覧 | リンク集 | RSS |
|
Haskellというプログラミング言語を勉強しているメモです。 注意: このコーナーのページは暫定的に公開しているものであり、 頻繁に修正・削除される可能性があります。
最近のHaskell勉強日記は、はてなグループで書いています。
既約分数クイズに対するHaskell版解答集。
適当な大きさの例題として、 Yuki::RSSをHaskellに移植しようと考えた。 作りかけたけれど、それ以前にハッシュテーブルや、 タグライブラリなどを作る/使うほうがよいとわかって中断。
\begin{code}
attr :: String -> String -> String
attr a v = a ++ "=\"" ++ v ++ "\""
xmlns_rdf = attr "xmlns:rdf" "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns = attr "xmlns" "http://purl.org/rss/1.0/"
xmlns_dc = attr "xmlns:dc" "http://purl.org/dc/elements/1.1/"
xmlhead enc = "<?xml " ++ (attr "version" "1.0") ++ " " ++ (attr "encoding" enc) ++ " ?>"
data Rss = Rss Head Channel Body
data Head = Head [(String, String)]
data Channel = Channel [(String, String)]
data Body = Body [Item]
data Item = Item [(String, String)]
addItem :: Rss -> Item -> Rss
addItem (Rss h c (Body is)) i = (Rss h c (Body (is++[i])))
instance Show Rss where
show (Rss h c b) = (headstr h) ++ (channelstr c) ++ (bodystr b)
where
itemstr :: Item -> String
headstr :: Head -> String
channelstr :: Channel -> String
bodystr :: Body -> String
headstr (Head []) = error "headstr"
headstr (Head (("encoding",enc):xs)) = (xmlhead enc) ++ "...\n"
headstr (Head ((x,y):xs)) = headstr (Head xs)
headstr _ = error "headstr"
channelstr _ = "...Channel...\n"
bodystr (Body (x:xs)) = (itemstr x) ++ (bodystr (Body xs))
bodystr _ = "\n"
itemstr _ = "...item...\n"
rss1 = Rss
(Head [
("version", "1.0"),
("encoding", "Shift_JIS")
])
(Channel [
("title", "Site Title"),
("link", "http://www.example.com/index.html"),
("about", "http://www.example.com/rss.rdf"),
("description ", "The description of your site")
])
(Body [
])
rss2 = addItem rss1
(Item [
("title", "Item Title"),
("link", "http://www.example.com/item.html"),
("description", "Yoo, hoo, hoo"),
("dc_date", "2003-12-06T01:23:45+09:00")
])
\end{code}
Main> rss1 <?xml version="1.0" encoding="Shift_JIS" ?>... ...Channel... Main> rss2 <?xml version="1.0" encoding="Shift_JIS" ?>... ...Channel... ...item...
CRAFT 12.3を読んでいる。
(==)と(/=)の定義が以下のようになっているのを見て、最初は驚いた。
class Eq a where
(==) :: a -> a -> Bool
x == y = not (x /= y)
(/=) :: a -> a -> Bool
x /= y = not (x == y)
無限ループになってしまうような気がしたからだ。 でも、そうではなく、 Eqのinstanceが、(==)と(/=)のどちらか一方でも定義すればよいということになる。
Javaでメソッドのoverrideというと、スーパークラスのメソッドをoverrideすることを意味するが、 Haskellではclassの演算子をinstanceがoverrideするらしい。
練習してみよう。
module Main where
data Color = Red | Pink | Green | Grass | Blue | Skyblue
instance Eq Color where
Red == Pink = True
Green == Grass = True
Blue == Skyblue = True
_ == _ = False
t1 = Red == Pink
t2 = Red /= Pink
t3 = Green == Skyblue
t4 = Green /= Skyblue
Main> t1 True Main> t2 False Main> t3 False Main> t4 True
ここでは、Colorというtypeに対して演算子(==)だけを定義している。 しかしちゃんと、(==)と(/=)が使えるようになっている。
ちなみに、ColorというtypeはEqというclassのinstanceである。 Javaのclassはtypeとほぼ同義だが、Haskellのclassはtypeの集まりである。 用語が微妙に違うので注意が必要である。
ところで、もしも(==)と(/=)の両方を定義しなかったらどうなるだろう。 以下のように、スタックオーバーフローを起こす。
module Main where data Color = Red | Pink | Green | Grass | Blue | Skyblue instance Eq Color t = Red == Pink
Main> t ERROR - C stack overflow
CRAFT 12.2, 12.3を見ながら、classの練習。
\begin{code}
module Main where
import Char
class Incrementable a where
inc :: a -> a
instance Incrementable Char where
inc c = chr ((ord c) + 1)
t1 = inc '3'
t2 = inc 'A'
instance Incrementable a => Incrementable [a] where
inc = map inc
t3 = inc ['A'..'D']
t4 = inc "HAL"
\end{code}
Main> t1 '4' Main> t2 'B' Main> t3 "BCDE" Main> t4 "IBM"
CRAFT 3.7 (p.51)とAppendix Cを見ながら、C言語風の % で `mod` の代わりにしてみる。
\begin{code}
module Main where
(%) :: Integral a => a -> a -> a
infixl 7 %
(%) = mod
t1 = 7 `mod` 3
t2 = 7 % 3
t3 = 7 `mod` (-3)
t4 = 7 % (-3)
t5 = 7 `mod` 0
t6 = 7 % 0
\end{code}
Main> t1 1 Main> t2 1 Main> t3 -2 Main> t4 -2 Main> t5 Program error: divide by zero Main> t6 Program error: divide by zero
アマゾンから Introduction to Functional Programming using Haskell が届いた。 でも、これを読むのはThe Craft of Functional Programmingを読み終えてからになるだろう。
The Craft of Functional Programmingをはじめから読んでいる。 これはとてもていねいなよい教科書である。
Hugsのコマンドに:findというのがあるのを知る。 たとえば、 :find map と入力すると、mapの定義をエディタで見ることができる。
秀丸エディタを設定するには、たとえば、次のようなバッチファイルからHugsを起動すると楽。
"C:\Program Files\Hugs98\Hugs" -E"C:\Hidemaru\Hidemaru.exe /j%%d %%s" %1 %2 %3 %4 %5 %6 %7 %8 %9
アマゾンからHaskellの本が届いた。
2006 [ 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 ]
2005 [ 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 ]
2004 [ 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 ]
book(3) / char(2) / compiler(3) / craft(5) / data(7) / enum(1) / geb(2) / hawiki(1) / hugs(1) / info(1) / io(3) / list(2) / map(3) / monad(16) / nobsun(12) / report(4) / sicp(2) / soe(8) / suchthat(2) / yaht(8)