葵天下

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

1340871235

sofのStateモナドの添削がわかりやすかった

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)

参考

ProductName すごいHaskellたのしく学ぼう!
Miran Lipovača
オーム社 / 2940円 ( 2012-05-23 )


静岡で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で書いてます。

田子の浦しらすフェスティバル

しらす祭り。生と茹でのしらす丼

1340870918

1340870920

1340870922

生しらすはちょっと苦味があるので、茹でしらすのほうが好きかなぁ。

今度は赤富士丼を食べにいこうっと。

はやし

渋谷に出張だと大抵はやしにいってしまう。

1339500778

1339500779

他の店も探さないとなぁ

HaskellでSchemeを実装する(エラーの導入)

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

ってやってるし、エラーを取り扱う場合のお作法なのかなぁ。

モナド変換子を重ねまくれ

すごい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に立ち戻ればいいでしょう。

ProductName すごいHaskellたのしく学ぼう!
Miran Lipovača
オーム社 / 2940円 ( 2012-05-23 )


Fedora17で仮想化

ヒトと技術が減少していて、サーバーメンテにコストをかけられなくなってきているので、実機のトラブル時の移行コストがかかりすぎて「移行しないでいいかー」という投げやりな事案が多く発生するようになり、資産がもったいないので自分の管理サーバーは仮想化環境でなんとかすることにした。

本見ながらやったけど、色々試してたらネットワークが繋がらなくなってどうしようもなくなったのでホストを再インストールしたという。

ProductName KVM徹底入門 Linuxカーネル仮想化基盤構築ガイド
平 初
翔泳社 / 3444円 ( 2010-07-08 )


ホストのインストールとか詳しくやらんでいいから、もっとネットワーク周りを充実させて欲しいなぁと思った。 私のニーズはサーバー群を集約して、複数のwebサーバーを一台で管理したいというニーズだったんだが、そこら辺の記述が妙に少ないなぁと。

ブリッジを使ったネットワーク環境の構築

まずはホストの設定、動くのを確認したらゲストをゆっくり設定すると問題の切り分けが簡単。

  1. ホストだけでネットワークの設定をして外部につながることを確認。
  2. /etc/sysconfig/network-scripts/のifcfg-em1をコピーしてブリッジの設定をしたらネットワークを再起動してつながることを確認。プロミスキャスモードの必要はない。

ネットワークマネージャの管理下ではなくなるのでFedora17の場合は画面右上のネットワークアイコンに☓がつくがつながることを確認すればOK

  1. ゲストOSをインストールするときにハードウェアのアドバンス設定にブリッジが出るので、本のようにドメイン設定をvirshで行わなくてもOK

その他トラブルシューティング

libvirtdの軌道はsystemctl

systemctl start libvirtd.service

sshの設定は

yum install openssh-server

つながらない場合はFireWallを疑う。GUIの設定が正しいように見えても再度sshのチェックを付け直すと上手くいったりする。

というわけで、virshの便利さに驚いた6月後半であった。

HaskellでSchemeを実装する

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))

裏・雅山流

ヨコゼキにて。

香りもいいし、酸と爽やかさのバランスもいい。飲み飽きしないしオススメ。あればまた買う。

1340524857