2018年1月8日月曜日

passwdコマンドでAuthentication token lock busy

passwdコマンドでハマる


簡単な事って意外とハマるとツボって抜け出せなくなる。
kernelビルドしなおして再起動した後rootのパスワード設定しようとしようとしたら
# passwd root
Changing password for user root
New UNIX password:
Retype new UNIX password:

passwd: Authentication token lock busy
#
エラーが出る、昔見たような見ないような記憶が定かではないエラーで、しばらく悩んだ。
たまたま見てみると、/bootがmountされていない、/etc/fstabを見てみると腐ってる。
面倒だったのでstage3で/を強制的に上書きしたのがfstabが腐った原因。

なので、remountしてfstabを修正
# mount -o remount,rw / 

リブート後、ちゃんと帰ってきました
アルチューのみんな、ちゃんとupdateしようね。

2018年1月7日日曜日

gentooのprofiles上がってたの知らなかった

New 17.0 profiles in the Gentoo repository.


正月終わって、いきなり、CPU脆弱性祭り、なんか「ほんとは知ってたんじゃないのぉ」的な感じもしなくはないが、まぁメーカーを信じるとして、その乗りでgentooのアップデート調べてたら...



gentoo profiles が2017-11-30に上がってたの気がつかなかった、しょうがないのでアップデート。
gccはgcc-6.4.0以上にしたよとか、gccのPIEをディフォルトしたから、ビルドしなおしてねってとか、最近、MeltdownやらSpectreなんかで、アップデートしろっていうから面倒だけど諦めてやりましょう...

Sparc勢は余裕なんだろう ワロス

2018年1月3日水曜日

正月に Monad Transformer

あけまして、おめでとうございます


ミソカから元旦にかけて、あるチューhighまーのまま、stack overflowをおこし、体ダルダルで飲みつづけてます、本年もよろしくお願いします。



まず、今年の抱負


理由は聞かないでください
  • 一番搾りは350ml缶2本まで
  • 焼酎は薄めます
  • 「セイッ」は月に一度にする
今年も頑張るぞ!

もなどとらんすふぉーまーってなんだよ


それは、よく分かってません、とりあえずモナドを合成することらしいですが、やってみました、あってるかどうかは分かりませんが、動くのでいいでしょう。

まず、普通のStateもなど


よくみるサンプル、Identityは恒等モナドっていって、関数で言うidみたいなもんだと思ってて、それのモナド用らしい。
type Stack = [Int]

push :: Int -> StateT Stack Identity ()
push x = state $ \xs -> ((), x:xs)

pop :: StateT Stack Identity Int
pop = state $ \(x:xs) -> (x, xs)

ghciで
*Main> f = do {push 5; pop; pop;}
*Main> runIdentity (runStateT f [1,2,3])
(1,[2,3])
*Main>

runStateTでStateTモナドを走らせたら、Identity aが帰ってくるので、更にrunIdentityで剥がしているだけ。

エラーの時どうする?


こうやってpopしまくると、エラーになる
*Main> f = do {push 5; pop; pop; pop; pop; pop;}
*Main> runIdentity (runStateT f [1,2,3])
*** Exception: /home/cuomo/Code/haskell/MonadTransformer/MonadStack.hs:18:15-32: Non-exhaustive patterns in lambda

*Main> 

これは、\(x:xs)のパターンマッチが腐って、エラーになる、これはエラーとして処理したい、そんな時はpopをお利口チャンににして

push2 :: Int -> ExceptT String (StateT Stack Identity) ()
push2 x = state $ \xs -> ((), x:xs)

pop2 :: ExceptT String (StateT Stack Identity) Int
pop2 = do
    s <- get
    case s of
        x:xs -> put xs >> return x
        otherwise -> throwError "Stack is empty"
元々の機能にエラー処理を追加したことが、前のpopと違うところ、これはこうやって使う

*Main> f = do {push2 5; pop2; pop2; pop2; pop2; pop2;}
*Main> runIdentity (runStateT (runExceptT f) [1,2,3,4,5,6,7])
(Right 4,[5,6,7])
*Main> runIdentity (runStateT (runExceptT f) [1,2,3])
(Left "Stack is empty",[])
*Main> 

スタックから取るのが無いのに、popすると結果にLeft値がはいって失敗が分かるようになる、タプルの中にLeft値と腐った空の配列入れてきてもらっても、無意味っぽいので、別の書き方で...

push3 :: Int -> StateT Stack (ExceptT String Identity) ()
push3 x = state $ \xs -> ((), x:xs)

pop3 :: StateT Stack (ExceptT String Identity) Int
pop3 = do
    s <- get
    case s of
        x:xs -> put xs >> return x
        otherwise -> throwError "Stack is empty"

StateTとExceptTの位置を変えて逆にすると、結果がRight値、またはLeft値で出てくるようになる。
*Main> f = do {pop3; pop3; pop3; pop3; pop3; pop3;}
*Main> runIdentity (runExceptT (runStateT f [1,2,3,4,5,6,7]))
Right (6,[7])
*Main> f = do {pop3; pop3; pop3; pop3; pop3; pop3; pop3; pop3}
*Main> runIdentity (runExceptT (runStateT f [1,2,3,4,5,6,7]))
Left "Stack is empty"
*Main> 

成功すれば、Right値に結果がくるまれて、失敗した場合、Left値にエラーの文字列が入ってくるようになる、こっちの方がウケが良さそうな気がする。

操作をログでとる


さらにWriterTで何を突っ込んで、何を取り出したのをログする機能を追加してみる

type Log = [String]

push4 :: Int -> StateT Stack (WriterT Log (ExceptT String Identity)) ()
push4 x = do
    tell ["push " ++ show x]
    state $ \xs -> ((), x:xs)

pop4 :: StateT Stack (WriterT Log (ExceptT String Identity)) Int
pop4 = do
    s <- get
    case s of
        x:xs -> do
            tell ["pop " ++ show x]
            put xs >> return x
        otherwise -> do
            throwError $ "Stack is empty"

同じように...

*Main> runIdentity (runExceptT (runWriterT (runStateT f [1,2,3,4,5,6,7])))
Right ((4,[5,6,7]),["push 5","pop 5","pop 1","push 10","pop 10","pop 2","pop 3","pop 4"])
*Main> runIdentity (runExceptT (runWriterT (runStateT f [1,2,3])))
Left "Stack is empty"
*Main> 
外側のタプルの右側に操作したログが追加されるようになる。

最後にIOは


じゃぁ、この中でIOの処理入れたいんだど、どうすればいい? って疑問がわくよね、ここで、Identity a が効いてくる、IOとIdentityってkindすると

Prelude> :m +Control.Monad.Identity
Prelude Control.Monad.Identity> :k Identity
Identity :: * -> *
Prelude Control.Monad.Identity> :k IO
IO :: * -> *
Prelude Control.Monad.Identity> 

にてるよね、そう、IdentityのところへIOを入れられるようになって、liftIOでリフトしてIOな関数を利用する。

push5 :: Int -> StateT Stack (WriterT Log (ExceptT String IO)) ()
push5 x = do
    liftIO $ putStrLn "pushしまーすぅ"
    tell ["push " ++ show x]
    state $ \xs -> ((), x:xs)

pop5 :: StateT Stack (WriterT Log (ExceptT String IO)) Int
pop5 = do
    s <- get
    liftIO $ putStrLn "popすんぞ"
    case s of
        x:xs -> do
            tell ["pop " ++ show x]
            put xs >> return x
        otherwise -> do
            throwError $ show "Stack is empty"

これで、main()から呼んでみると
main :: IO ()
main = do
    v <- runExceptT (runWriterT (runStateT stackIjily [1,2,3,4,5,6,7]))
    putStrLn $ show v

stackIjily :: StateT Stack (WriterT Log (ExceptT String IO)) Int
stackIjily = do
    push5 5
    pop5
    pop5
    push5 10
    pop5
    pop5
    pop5
    pop5
    pop5
    x <- pop5
    return x

こうやると、関数の中でIOを発行することができる。

~/Code/haskell/MonadTransformer $ runghc MonadStack.hs
pushしまーすぅ
popすんぞ
popすんぞ
pushしまーすぅ
popすんぞ
popすんぞ
popすんぞ
popすんぞ
popすんぞ
popすんぞ
Right ((6,[7]),["push 5","pop 5","pop 1","push 10","pop 10","pop 2","pop 3","pop 4","pop 5","pop 6"])

こうやって、モナドを積んでいけば、既存の処理を壊すこと無く機能を追加できる、ただ、積み上げる順序によって剥がし方がかわるのと、ちょっと複雑になると分かりにくくなってしまうような気がする。まぁ慣れればそんなに気にする事でもなさそうな。

その他の、同じようなやつ


で、同じような理由で、RWSモナドとか、MonadWriterとかMonadStateとかMonadReaderとかあるみたいだけど、使ったこと無いです、こんどやってみます。

今年は、haskellの理解力をさらに深めたいと思います。