Hatena::ブログ(Diary)

趣味的にっき このページをアンテナに追加 RSSフィード

2007-08-07

[] HaskellぽいListライブラリ - Halu 07:24  HaskellぽいListライブラリ - Haluを含むブックマーク  HaskellぽいListライブラリ - Haluのブックマークコメント

Cohiはあまりにマニアックすぎるので、もう少しふつうの人を狙ってHaskellぽいListライブラリを作ってみようかと思います。こんな感じで使えるやつ。

include Halu

p List[1, 2, 3]
# => Halu::List::[1, 2, 3]

p List[]
# => Halu::EmptyList::[]

p(List[1, 2, 3].map2 {|h| h * 2 })
# => Halu::List::[2, 4, 6]

p(List[1, 2, 3].last)
# => 3

p(List[1, 2, 3].append(List[4, 5, 6]))
# => Halu::List::[1, 2, 3, 4, 5, 6]

p(List[1, 2, 3].filter {|h| h % 2 == 1 })
# => Halu::List::[1, 3]

p(List[1, 2, 3].init)
# => Halu::List::[1, 2]

p(List[1, 2, 3].length)
# => 3

名前はもう決っています。Haluです。HAskell like List Utility。とりあえずRubyForgeプロジェクト申請しておこうかな。

以下、現状のソースHaskellPreludeから実装予定の関数ピックアップしました。まだ全然実装されていません。第二回開発合宿に期待か?

#!/usr/bin/env ruby
# -*- compile-command: "ruby halu.rb" -*-

module Halu
  class List
    include Enumerable

    def List::[](*ary)
      root = list = EMPTY_LIST
      ary.each do |h|
        list = list << h
        root = list if root.null?
      end
      root
    end

    def initialize(h, t = EMPTY_LIST)
      @head = h
      @tail = t
    end

    def each
      list = self
      loop do
        yield(list.head)
        break if list.tail.null?
        list = list.tail
      end
      self
    end

    def to_a
      inject([]) {|ary, h| ary << h }
    end

    def inspect
      self.class.to_s + '::' + to_a.inspect
    end

    def last_list
      list = self
      list = list.tail until list.tail.null?
      list
    end
    private :last_list

    def <<(h)
      last_list.tail = List.new(h)
    end

    # map :: (a -> b) -> [a] -> [b]
    def map2
      root = list = EMPTY_LIST
      each do |h|
        list = list << yield(h)
        root = list if root.null?
      end
      root
    end

    # (++) :: [a] -> [a] -> [a]
    def append(list)
      last_list.tail = list
      self
    end

    # filter :: (a -> Bool) -> [a] -> [a]
    def filter
      root = list = EMPTY_LIST
      each do |h|
        if yield(h)
          list = list << h
          root = list if root.null?
        end
      end
      root
    end

    # head :: [a] -> a
    attr_accessor :head

    # last :: [a] -> a
    def last
      inject(nil) {|r, h| h }
    end

    # tail :: [a] -> [a]
    attr_accessor :tail

    # init :: [a] -> [a]
    def init
      root = list = prelist = EMPTY_LIST
      each do |h|
        prelist = list
        list = list << h
        root = list if root.null?
      end
      prelist.tail = EMPTY_LIST
      root
    end

    # null :: [a] -> Bool
    def null?
      self == EMPTY_LIST
    end

    # length :: [a] -> Int
    def length
      inject(0) {|r, h| r.succ }
    end

    # (!!) :: [a] -> Int -> a
    # reverse :: [a] -> [a]
    # foldl :: (a -> b -> a) -> a -> [b] -> a
    # foldl1 :: (a -> a -> a) -> [a] -> a
    # foldr :: (a -> b -> b) -> b -> [a] -> b
    # foldr1 :: (a -> a -> a) -> [a] -> a
    # and :: [Bool] -> Bool
    # or :: [Bool] -> Bool
    # any :: (a -> Bool) -> [a] -> Bool
    # all :: (a -> Bool) -> [a] -> Bool
    # sum :: Num a => [a] -> a
    # product :: Num a => [a] -> a
    # concat :: [[a]] -> [a]
    # concatMap :: (a -> [b]) -> [a] -> [b]
    # maximum :: Ord a => [a] -> a
    # minimum :: Ord a => [a] -> a
    # scanl :: (a -> b -> a) -> a -> [b] -> [a]
    # scanl1 :: (a -> a -> a) -> [a] -> [a]
    # scanr :: (a -> b -> b) -> b -> [a] -> [b]
    # scanr1 :: (a -> a -> a) -> [a] -> [a]
    # iterate :: (a -> a) -> a -> [a]
    # repeat :: a -> [a]
    # replicate :: Int -> a -> [a]
    # cycle :: [a] -> [a]
    # take :: Int -> [a] -> [a]
    # drop :: Int -> [a] -> [a]
    # splitAt :: Int -> [a] -> ([a], [a])
    # takeWhile :: (a -> Bool) -> [a] -> [a]
    # dropWhile :: (a -> Bool) -> [a] -> [a]
    # span :: (a -> Bool) -> [a] -> ([a], [a])
    # break :: (a -> Bool) -> [a] -> ([a], [a])
    # elem :: Eq a => a -> [a] -> Bool
    # notElem :: Eq a => a -> [a] -> Bool
    # lookup :: Eq a => a -> [(a, b)] -> Maybe b
    # zip :: [a] -> [b] -> [(a, b)]
    # zip3 :: [a] -> [b] -> [c] -> [(a, b, c)]
    # zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
    # zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d]
    # unzip :: [(a, b)] -> ([a], [b])
    # unzip3 :: [(a, b, c)] -> ([a], [b], [c])
    # lines :: String -> [String]
    # words :: String -> [String]
    # unlines :: [String] -> String
    # unwords :: [String] -> String
  end

  class EmptyList < List
    def initialize
    end

    def each
    end
    
    def to_a
      []
    end

    def <<(h)
      List.new(h)
    end
  end

  EMPTY_LIST = EmptyList.new
end

[] 07:24 を含むブックマーク のブックマークコメント

18:00ごろ帰りました。

Connection: close