Haskellで安全なファイルのオープン

例外処理をやるためにhandleとbracketがある。

Prelude> :m +Control.OldException
Prelude Control.OldException> :t handle
handle :: (Exception -> IO a) -> IO a -> IO a
Prelude Control.OldException> :t bracket
bracket :: IO a -> (a -> IO b) -> (a -> IO c) -> IO c

handleは最初の引数に処理が失敗した時の例外ハンドラ。本ではファイルのサイズを返す関数を書くときに使っていて、openに失敗したらNothingを返すようなアクションを定義してた。

bracketは最初のアクションでリソース獲得、二番目のアクションがリソース開放、最後のアクションがリソース獲得から開放までにはしるアクション。pythonでいうところのtry-except-finallyみたいなものか。

RWHではhandleとbracketを組み合わせて

getFileSize path = handle (\_ -> return Nothing) $
  bracket (openFile path ReadMode) hClose $ \h -> do
    size <- hFileSize h
    return (Just size)

ってなってんだけど、もしhandleなしでbracketのopenが失敗して例外が返ったらどうなんのとか?基本的にhandleとbracketは組み合わせて使うものなのか?

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan,John Goerzen,Don Stewart
オライリージャパン / ¥ 3,990 ()
在庫あり。

HaskellでEmacsのバックアップファイルを探す

9章のforMの練習

forM :: (Monad m) => [a] -> (a -> m b) -> m [b]

リストと、関数をとってリストのモナドを返す

module RecursiveContents (getRecursiceContents) where

import Control.Monad (forM)
import System.Directory (doesDirectoryExist, getDirectoryContents)
import System.FilePath ((</>))
import Text.Regex.Posix ((=~))

getRecursiceContents :: FilePath -> IO [FilePath]
getRecursiceContents topdir = do
  names <- getDirectoryContents topdir
  let properNames = filter (`notElem` [".", ".."]) names
  paths <- forM properNames $ \name -> do
    let path = topdir </> name
    isDirectory <- doesDirectoryExist path
    if isDirectory
       then getRecursiceContents path
       else 
           if path =~ ".+~$"
           then return [path]
           else return []
  return (concat paths)

実行

$ ghci RecursiveContents.hs 
*RecursiveContents> getRecursiceContents "/Users/kzfm/perl"
["/Users/kzfm/perl/hori.pl~","/Users/kzfm/perl/Moosp/lib/Moosp/Function \
/Defun.pm~","/Users/kzfm/perl/Moosp/t/17-function-defun.t~"]

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan,John Goerzen,Don Stewart
オライリージャパン / ¥ 3,990 ()
在庫あり。

doesDirectoryExist関数はアクションで返り値はIO Boolのため、<-でBoolにする必要がある。

そば屋はなぜ領収書を出したがらないのか?

タイトルは微妙だが、領収書に関するアレコレ。

  • 資本取引
  • 会社の経費の領収書を社員がもらうときには「会社の宛名にしなきゃダメ」というのは社内規定であって、税務申告上にはそんなものはない
  • 修繕費は原則経費だが、修繕することによりその価値が高まる場合には固定資産として計上する

Haskellで正規表現

RWH8章のメモ

Haskellの正規表現のための演算子は=~でperlと一緒だ。

Prelude> :m +Text.Regex.Posix
Prelude Text.Regex.Posix> "Haskell" =~ "^.+ll$" :: Bool
Loading package syb ... linking ... done.
Loading package array-0.2.0.0 ... linking ... done.
Loading package bytestring-0.9.1.4 ... linking ... done.
Loading package regex-base-0.72.0.2 ... linking ... done.
Loading package regex-posix-0.72.0.3 ... linking ... done.
True

さらに型の指定を変えると、それに合わせた値を返してくる。(Int,Int)とか。=~の型が気になるので:tして後悔した。

Prelude Text.Regex.Posix> :t (=~)
(=~)
  :: (Text.Regex.Base.RegexLike.RegexMaker
        Regex CompOption ExecOption source,
      Text.Regex.Base.RegexLike.RegexContext Regex source1 target) =>
     source1 -> source -> target

ぶっちゃけ全然わからん。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan,John Goerzen,Don Stewart
オライリージャパン / ¥ 3,990 ()
在庫あり。

Haskellのファイル入出力(RWH 7章)

抽象度を上げていく。

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan,John Goerzen,Don Stewart
オライリージャパン / ¥ 3,990 ()
在庫あり。

ファイルを読んで、コンテンツを大文字に変えてファイルに書き込む処理を考える。これはハンドルを開いて読み書きすればいい。

import System.IO
import Data.Char(toUpper)

main :: IO ()
main = do
  inh <- openFile "input.txt" ReadMode
  outh <- openFile "output.txt" WriteMode
  mainloop inh outh
  hClose inh
  hClose outh

mainloop :: Handle -> Handle ->IO ()
mainloop inh outh =
    do ineof <- hIsEOF inh
       if ineof then return ()
                else do inpStr <- hGetLine inh
                        hPutStrLn outh $ processData inpStr
                        mainloop inh outh

processData :: String -> String
processData = map toUpper

このmainloop関数はEOFが見つかるまでストリームを読んでいくが、これはhGetContentsで抽象化出来る

import System.IO
import Data.Char(toUpper)

main :: IO()
main = do
  inh <- openFile "input.txt" ReadMode
  outh <- openFile "output.txt" WriteMode
  inpStr <- hGetContents inh
  let result = processData inpStr
  hPutStr outh result
  hClose inh
  hClose outh

processData :: String -> String
processData = map toUpper

さらに、さらにハンドルを開いて文字列を読み出す処理と、文字列に大して何らかの処理をしながら、ハンドルを開いてファイルに書き出すという処理もそれぞれreadFile,writeFileで抽象化できるので、結局次のようになる

import Data.Char(toUpper)

main = do
  inpStr <- readFile "input.txt"
  writeFile "output.txt" $ processData inpStr

processData :: String -> String
processData = map toUpper

となると、読み出すファイル名と、書き出すファイル名と、ストリームに対し作用させる関数を受け取ってよろしくやってくれる関数まであっていいと思うのだけど、それは標準ライブラリに存在するのだろうか?

convert readfile writefile (map toUpper)

みたいなの。

Practical Arduino

クリスマスイブに出る新刊ということは、ポチっと押さなくても靴下用意して寝ておけば 次の朝には入ってる可能性もないことはない。

気がするが、、、、、、結局ポチった。

手打ち蕎麦 ふかさわ

昨日は娘を病院に連れていったりして午後から出社したので、昼はどこかで食べていくことにした。

いくつか候補があったのだけど、手打ち蕎麦 ふかさわへ。

1259980592

十里木の別荘地帯?の入り口に近いが少し入ったところにあるので静かだ。

1259980606 1259980612

中は、落ち着いた感じで、窓が大きいので外の景色を見ていて飽きない。

注文したのはおかめ蕎麦。

1259980600

次はせいろを注文したい。

本を購入

本をまとめ買いした。

ProductName 入門Git
濱野 純(Junio C Hamano)
秀和システム / 2310円 ( 2009-09-19 )


ProductName Linux-DB システム構築/運用入門 (DB Magazine SELECTION)
松信 嘉範
翔泳社 / 2814円 ( 2009-09-17 )


ProductName ビューティフルアーキテクチャ (THEORY/IN/PRACTICE)

オライリージャパン / 3150円 ( 2009-11-27 )


ProductName Linuxカーネル2.6解読室
高橋浩和
ソフトバンククリエイティブ / 5670円 ( 2006-11-18 )


LOLは今回は買わないでおいた。

美文書作成入門は新版でるっていう噂を聞いたのでそれまで待つ。

ProductName [改訂第4版] LaTeX2ε美文書作成入門
奥村 晴彦
技術評論社 / ?円 ( 2006-12-12 )


RWH5章

JSONライブラリを作る

ProductName Real World Haskell―実戦で学ぶ関数型言語プログラミング
Bryan O'Sullivan,John Goerzen,Don Stewart
オライリージャパン / ¥ 3,990 ()
在庫あり。

GHCのパッケージマネージャはpython setup.py buildみたいな感じでらくちん。

ただ、この章をやってみて、分かり難い箇所が二点あった。

一つ目は5.9「混乱せずにHaskellコードを開発する」という章でスタブに触れられていて、かつPrettyStub.hsというコードが載っているのだけど、本文中で実際に実行されていない。そのため、このコードをどう使っていいのかいまいち理解できなかった。Developing Haskell code without going nutsでも同じようなコメントがあった。

二つ目はPrettify.hsのモジュール宣言に触れられてなかったので

module Prettify where

ってつけといた。

Haskellでスタブを利用する時のわかりやすい説明どっかにないかな

白岳仙 純米ひやおろし

先週、静岡にいった際に、今日はまっすぐ帰ってくるように言われていたので、コメヤスさんにお邪魔してきたのであった。

一年ぶりくらい(多分静岡もそのくらいぶり)で、いろいろ欲しい物があって迷ったけど、既にmacbook抱えていで一升瓶二本はちょっと持てない気がしたので、白岳仙のひやおろしを一本いただいて帰った。

1259837851

人肌燗でということだったので、ぬる目で燗つけて、そのあと冷やで。ゆるりとしていて旨い。