29062012 sake
キリリ感を感じさせる、静岡っぽい感じの日本酒だなぁと

29062012 Haskell
Working with the State monad in Haskell
collectUntil :: (s -> Bool) -> State s a -> State s [a] collectUntil f s = do s0 <- get let (a,s') = runState s s0 put s' if (f s') then return [a] else liftM (a:) $ collectUntil f s
これはliftM使いすぎでbind使わなさすぎなコードらしく、次のようになおされてた。
collectUntil2 :: MonadState t m => (t -> Bool) -> m a -> m [a] collectUntil2 f s = do s' <- get if f s' then return [] else do x <- s xs <- collectUntil2 f s return (x:xs)
確かにこっちのほうが(State s)の配管を引っ張りだしてなくて見やすいかもなぁと思いつつ、bindを明示的に書いてみた。
collectUntil3 :: MonadState t m => (t -> Bool) -> m a -> m [a] collectUntil3 f s = get >>= \s' -> if f s' then return [] else s >>= \x -> collectUntil3 f s >>= \xs -> return (x:xs)
参考
28062012 Node.js
最近完全にHaskellにシフトしてる感がありますが、明後日(6/30)の土曜日に静岡でNode.jsハンズオンをやります
キャンセルが出てて若干空きがあるみたいなんで、時間があれば参加するといいと思います。
スライドつくったのでGithubにpushしておきました。
git clone git@github.com:kzfm/shizdraw.git cd shizdraw/slides python -m SimpleHTTPServer # http://localhost:8000/で立ち上がる
でスライドを見ることができます。ちなみにコードはCoffeeScriptで書いてます。
28062012 富士
28062012 Haskell
Write Yourself a Scheme in 48 Hoursを読んでいる。4章のエラーチェッキングのあたり。
LispErrorを定義して、それをHaskellの組み込みのエラー関数で使えるようにする。
MonadErrorのインスタンスにすればthrowErrorとcatchErrorが使えるが、そのためにはEither型の左側をErrorクラスのインスタンスにする必要がある。
instance Error e => MonadError e (Either e) where throwError = Left Left l `catchError` h = h l Right r `catchError` _ = Right r
コード中ではここ。
type ThrowsError = Either LispError instance Show LispVal where show = showVal instance Show LispError where show = showError instance Error LispError where noMsg = Default "An error has occurred" strMsg = Default
typeで別名をつけているのは取り回しを楽にするためかな?Error モナドを読んでも
type ParseMonad = Either ParseError
ってやってるし、エラーを取り扱う場合のお作法なのかなぁ。
27062012 Haskell
すごいHaskellのモナド変換子を理解したら読めばいいと思います、というか読むべき。超わかりやすかった。合体ロボ並に合成されて強そうな型に変換していく様は圧巻のゴーカイジャー(見てないからしらんけど)
スマイルプリキュアで例えると、「プリキュア・レインボーヒーリング」ですね(多分)。
最初に簡単な評価器からはじめる
eval0 :: Env -> Exp -> Value
という型から始めてモナドにする。
type Eval1 a = Identity a
次にエラーモナド変換子を重ねて
type Eval2 a = ErrorT String Identity a
環境であるReaderTを重ねる
type Eval3 a = ReaderT Env (ErrorT String Identity) a
続いて、状態を重ねる
type Eval4 a = ReaderT Env (ErrorT String (StateT Integer Identity)) a
ログ機能を導入して
type Eval5 q = ReaderT Env (ErrorT String (WriterT [String ] (StateT Integer Identity))) q
最後にお約束のIO
type Eval6 a = ReaderT Env (ErrorT String (WriterT [String ] (StateT Integer IO))) a
順番にテンポよく積み上がっていくので、読んでて悩むことなく最後の型まで到達できるので素晴らしい。英語も平易だし。
さらっと読んでみてよく分からなかったら、すごいHaskellに立ち戻ればいいでしょう。
26062012 Linux
ヒトと技術が減少していて、サーバーメンテにコストをかけられなくなってきているので、実機のトラブル時の移行コストがかかりすぎて「移行しないでいいかー」という投げやりな事案が多く発生するようになり、資産がもったいないので自分の管理サーバーは仮想化環境でなんとかすることにした。
本見ながらやったけど、色々試してたらネットワークが繋がらなくなってどうしようもなくなったのでホストを再インストールしたという。
ホストのインストールとか詳しくやらんでいいから、もっとネットワーク周りを充実させて欲しいなぁと思った。 私のニーズはサーバー群を集約して、複数のwebサーバーを一台で管理したいというニーズだったんだが、そこら辺の記述が妙に少ないなぁと。
まずはホストの設定、動くのを確認したらゲストをゆっくり設定すると問題の切り分けが簡単。
ネットワークマネージャの管理下ではなくなるのでFedora17の場合は画面右上のネットワークアイコンに☓がつくがつながることを確認すればOK
libvirtdの軌道はsystemctl
systemctl start libvirtd.service
sshの設定は
yum install openssh-server
つながらない場合はFireWallを疑う。GUIの設定が正しいように見えても再度sshのチェックを付け直すと上手くいったりする。
というわけで、virshの便利さに驚いた6月後半であった。
25062012 Haskell
Paesecの使い方の勉強も兼ねてWrite Yourself a Scheme in 48 Hoursをやりはじめた。
Parser書くとこまではすんなり終了。
import System.Environment import Text.ParserCombinators.Parsec hiding (spaces) import Control.Monad data LispVal = Atom String | List [LispVal] | DottedList [LispVal] LispVal | Number Integer | String String | Bool Bool instance Show LispVal where show = showVal symbol :: Parser Char symbol = oneOf "!#$%&|*+-/:<=>?@^_~" spaces :: Parser () spaces = skipMany1 space parseString :: Parser LispVal parseString = do char '"' x <- many (noneOf "\"") char '"' return $ String x parseAtom :: Parser LispVal parseAtom = do first <- letter <|> symbol rest <- many (letter <|> digit <|> symbol) let atom = first:rest return $ case atom of "#t" -> Bool True "#f" -> Bool False _ -> Atom atom parseNumber :: Parser LispVal parseNumber = liftM (Number . read) $ many1 digit parseList :: Parser LispVal parseList = liftM List $ sepBy parseExpr spaces parseDottedList :: Parser LispVal parseDottedList = do head <- endBy parseExpr spaces tail <- char '.' >> spaces >> parseExpr return $ DottedList head tail parseQuoted :: Parser LispVal parseQuoted = do char '\'' x <- parseExpr return $ List [Atom "quote", x] parseExpr :: Parser LispVal parseExpr = parseAtom <|> parseString <|> parseNumber <|> parseQuoted <|> do char '(' x <- try parseList <|> parseDottedList char ')' return x showVal :: LispVal -> String showVal (String contents) = "\"" ++ contents ++ "\"" showVal (Atom name) = name showVal (Number contents) = show contents showVal (Bool True) = "#t" showVal (Bool False) = "#f" showVal (List contents) = "(" ++ unwordsList contents ++ ")" showVal (DottedList head tail) = "(" ++ unwordsList head ++ " . " ++ showVal tail ++ ")" unwordsList :: [LispVal] -> String unwordsList = unwords . map showVal readExpr :: String -> String readExpr input = case parse parseExpr "lisp" input of Left err -> "No match: " ++ show err Right val -> "Found " ++ show val main :: IO () main = do args <- getArgs putStrLn (readExpr (args !! 0))