2005年1月

Haskell

目次

2005年1月13日

Yuki::RSSをHaskellに移植→中断 2005年1月13日 11:10

適当な大きさの例題として、 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...

feedback | top

Default definitions 2005年1月13日 09:29 [craft]

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

feedback | top

2005年1月8日

class, instance 2005年1月8日 22:11 [craft]

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"

feedback | top

Do-it-yourself operators 2005年1月8日 15:35 [craft]

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

feedback | top

2005年1月7日

Introduction to Functional Programming using Haskell 2005年1月7日 23:21 [book]

アマゾンから Introduction to Functional Programming using Haskell が届いた。 でも、これを読むのはThe Craft of Functional Programmingを読み終えてからになるだろう。

feedback | top

2005年1月5日

:find 2005年1月5日 20:45 [craft]

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

feedback | top

2005年1月4日

Haskellの本 2005年1月4日 22:30 [craft]

アマゾンからHaskellの本が届いた。

feedback | top

2005年1月3日

テンポを落とします 2005年1月3日 23:12

あけましておめでとうございます。 昨年末は妙にHaskellに燃えてしまいましたが、 今年はもう少しじっくり学んでいこうと思います。 ので、更新はぼちぼちと。

feedback | top

記事一覧

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 ]

Bloglines

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)

記事検索 サイト検索はこちら

豊かな人生のための四つの法則