トップ «前の日記(2008-08-10) 最新 次の日記(2008-08-19)» 編集

Route 477



2008-08-13

[ruby] ruby Functor gem

RubyでHaskellやOCamlのようなパターンマッチを実現しようという試みはいくつもありますが、それらの中では一番綺麗なんじゃないでしょうか(見た目的な意味で)。

fib = Functor.new do
  given( 0 ) { 0 }
  given( 1 ) { 1 }
  given( Integer ) { |n| self.call( n - 1 ) + self.call( n - 2 ) }
end

どうでしょうか?

ところでFunctorって一体なんなんでしょう。いろんなところで名前だけは聞くのですが…。

関手(かんしゅ、functor)とは、圏論における一つの圏から別の圏への対応でその構造と両立するようなものである。関手によって一つの数学体系から別の体系へのシステマティックな対応が定式化される。関手は「圏の圏」における射と考えることもできる。

[関手 - Wikipediaより引用]

分かる要素がないwww

[ruby] RubyTreemap

ハードディスクの使用状況を、地図のように分かりやすく表示してくれるソフトウェアがあります。例えばSpaceMongerとか。

RubyTreemapは、このような画像を簡単に作るためのライブラリだそうです。PNG, SVGのほか、htmlでも出力できる模様

しかし、ハードディスクの使用状況以外でどういう用途に使えるんでしょう?ツリーの各節点が何かの大きさを持つような構造といえば…。うーん、何だろう。

(追記: 例えば家計簿の支出を階層構造のカテゴリに分けると、「今月本にはこれくらい使って、そのうち漫画はこれくらい」とか分かっていいかも。)

[haskell] HUnitを使ってみた

(追記:Test.HUnitはGHCだと標準で入ってます。インストールは不要。)

一応AssertEqualとかもあるんですけど、そうじゃなくて演算子の方を使うのが玄人らしい。

僕はRSpecが好きなので~?= を使ってますが、 ~=?を使えば逆順 (つまり <expected> ~=? <given>) で書くこともできます。

plus3.hs:

module Plus3 where                                                                       
 
plus3 :: Int -> Int -> Int -> Int
plus3 x y z = x + y + z  

test_plus3.hs:

import Test.HUnit
import Plus3
 
simpleTest =  
  [ "plus3 should plus 3 integers" ~:
      (plus3 1 2 3) ~?= 6
  , "plus3 should plus 3 negative integers" ~:
      plus3 (-1) (-2) (-3) ~?= -6
  ]
 
largeTest =
  [ "plus3 should plus 3 large integers" ~:
      (plus3 1000000000000000000000000
             2000000000000000000000000
             3000000000000000000000000) ~?= 6000000000000000000000000
  ]
               
testData = [ "simple" ~: simpleTest
           , "large data" ~: largeTest
           ]
 
main = runTestTT (test testData)

実行結果:

/Users/yhara/proj/babel21/haskell % runghc test_plus3.hs
Cases: 3  Tried: 3  Errors: 0  Failures: 0

MacPortsで入れたGHC 6.8.2で確認。

[haskell] Haskellで外部プログラムとパイプ経由でやりとりしてみた

Rubyでいうopen3である。

import System.Process                                                                    
import System.IO                                                                         
                                                                                         
main :: IO ()                                                                            
main = do (stdin, stdout, stderr, processHandle) <- runInteractiveCommand "sort"         
          hPutStr stdin "foo\nbar\nbaz"                                                  
          result <- hGetContents stdout                                                  
          putStr result 

どう見ても手続き型ですw 思ったより簡単だな。

実行結果:

/Users/yhara/proj/babel21/haskell % runghc process_sample.hs
bar
baz
foo
本日のツッコミ(全3件) [ツッコミを入れる]
soutaro (2008-08-14 02:04)

"Introducing Functor"の"Functor"はちょっとわからなかったのですが、MLやC++のfunctorは「関数みたいだけど関数ではないもの」ぐらいの感じだと昔聞いたことがあります。数学での定義は私もよくわかっていないのですが、「関手は「圏の圏」における射と考えることもできる。」というのも、そんなような感じじゃないかと思います。

minke (2008-08-14 03:10)

functorという言葉は、プログラミング言語界隈では圏論の関手の意味を超えてもっと広くゆるく使われてますね。<br>圏論の関手は圏から圏への写像で、何を圏とみなすかでいろいろ変わってきます。<br>HaskellのFunctorクラスは一応「型を対象とし関数を射とする圏」を写すものっぽい感じになってます。MLのfunctorは単なるモジュールからモジュールへの写像です。C++やこの例のfunctorはあまり圏論の関手を意識してつけられたネーミングではなさそうです。ほんと「関数っぽいもの」ぐらいのノリですかね。

yhara (2008-08-18 13:58)

soutaroさん、minkeさん:<br>ありがとうございます。必ずしも「Functor == 関手」の意味で使われてるわけではないのですね。<br>「Function => 関数、Functor => 関数っぽいもの」か。なるほど。