第二回Haskell読書会開催

来週の土曜日に第二回Haskell読書会が静岡であります。

プログラミングHaskellの3章を読みます。

ProductName プログラミングHaskell
Graham Hutton
オーム社 / ¥ 2,940 ()
在庫あり。

次の日は朝から簿記試験なので、懇親会にはまたもやでられない。残念。

Scalaのzipが

なんか慣れない。

scala> Array(1,2,3) zip Array(4,5,6)
res1: Array[(Int, Int)] = Array((1,4), (2,5), (3,6))

Haskellだとこんな感じでしょ。

Prelude> [1,2,3] `zip` [4,5,6]
[(1,4),(2,5),(3,6)]

Pythonだと

[1,2,3].zip([4,5,6])

とはできない。

>>> zip([1,2,3],[4,5,6])
[(1, 4), (2, 5), (3, 6)]

HaskellのArrow

Arrowを学ぶ。Programming with Arrowsを読んでから、「Arrowのはなし」というニコニコ動画をみるのがわかりやすい。イメージは3番目が参考になる。

Arrowを使って奇数列を作ってみる。 0から始まる数列を&&&で分岐させて一方はそのまま戻して、もう一方はtailすることで1から始まる数列にして、合流したら足し合わせる。

Prelude Control.Arrow> let odds = (tail) &&& id >>> (uncurry (zipWith (+)))
Prelude Control.Arrow> take 10 $ odds [0,1..]
[1,3,5,7,9,11,13,15,17,19]

他、参考にしたサイト

RWHではArrowは15.4.2にちょっとだけ触れられている。

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

Haskellでcat

bindの使い方メモ

import System.Environment

cat:: String -> IO ()
cat = (>>= putStr) . readFile

main = do (file:_) <- getArgs; cat file

追記10.02.13

コメントよりheadを使えば一行で書ける。

main=getArgs>>=readFile.head>>=putStr

Hakellでテンポラリディレクトリやテンポラリファイル

テンポラリファイルをエディタでいじって、保存するとテンポラリファイルの内容を読んでHsSyckでパースして出力する

import System.IO
import System.Process
import System.Directory
import System.Environment
import Control.Monad (liftM)
import Data.Yaml.Syck

main :: IO ()
main = do
  tmpdir <- getTemporaryDirectory
  (pathOfTempFile, h) <- openTempFile tmpdir "temp.yaml"
  editor   <- liftM (lookup "EDITOR") getEnvironment
  case editor of Just ed -> (>>= waitForProcess) . runCommand $ ed ++ " " ++ pathOfTempFile
                 Nothing -> error "command error\n"
  hClose h

  inpStr <- readFile pathOfTempFile
  yamlstr <- parseYaml inpStr
  print yamlstr

  removeFile pathOfTempFile
  return ()

HoogleGHCの標準ライブラリドキュメントが手放せない身体になってきた。

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

もっとHaskellの本出ないかなぁ。Principles of Biomedical InformaticsのHaskell阪みたいなのとか。

ProductName Principles of Biomedical Informatics
Ira J. Kalet PhD
Academic Press / ¥ 7,667 ()
通常1~3週間以内に発送

HaskellでPitを使う

perlにもConfig::Pitあるし、Pythonにもあるしという状況なので、Haskellでネットワークのちょろっとしたものを書くときにもパスワードをハードコードしないで、pitのやつを使いたかった。

module HsPit (
            pitGet,
            pitSet
           )
where

import System.FilePath ((</>))
import System.Directory
import Data.Yaml.Syck

pitGet :: String -> IO [(String,String)]
pitGet query = do
  home <- getHomeDirectory
  do yaml <- parseYamlFile (home </> ".pit" </> "default.yaml")
     case n_elem yaml of
       EMap list -> return $ map (\keyval -> (,) ((fromYaml . fst) keyval) ((fromYaml . snd) keyval)) $ concatMap (fromEMap . snd) $ filter checkElem list
           where checkElem ynode = ((n_elem . fst) ynode) == (EStr (packBuf query))
       otherwise -> return []
       where 
         fromYaml MkNode {n_elem=EStr str}   = unpackBuf str
         fromEMap MkNode {n_elem=EMap nodes} = nodes

pitSet = error "Not implemented"

HsSyckの使い方はPugsのYamlコードを参考にした。

で、例えばtwitterでつぶやくときには

import Network.HTTP
import Network.URI
import Codec.Binary.Base64.String
import Data.Maybe
import HsPit

tweet username password msg = simpleHTTP req where 
    req = Request uri POST [ah] "" where
        ah = Header HdrAuthorization $ "Basic " ++ encode (username ++ ":" ++ password)
        uri = fromJust $ parseURI $ "http://twitter.com/statuses/update.xml?" 
              ++ urlEncodeVars [("status", msg)]

main = do 
  userdata <- pitGet "twitter"
  case lookup "username" userdata of Just username ->
                                         case lookup "password" userdata of Just password ->
                                                                                tweet username password "tWeet"

なんかごちゃごちゃとしてしまった。

HaskellでYAML

HaskellでYAMLを扱うライブラリはyaml,HsSyckがあるんだけどlibyamlのバインディングであるyamlのほうは使い方がわからん。

なので、HsSyckの使い方を覚えた。

import Data.Yaml.Syck

global_tag  = mkNode $ EStr $ packBuf "Item 1"
name_tag    = mkNode $ EStr $ packBuf "name"
name_value  = mkNode $ EStr $ packBuf "kzfm"
email_tag   = mkNode $ EStr $ packBuf "address"
email_value = mkNode $ EStr $ packBuf "xxx@gmail.com"
pass_tag    = mkNode $ EStr $ packBuf "password"
pass_value  = mkNode $ EStr $ packBuf "snail"

item = mkNode $ EMap [(name_tag,name_value),(email_tag,email_value),(pass_tag,pass_value)]
node = mkNode $ EMap [(global_tag,item)]

main = do
  emitYamlFile "test.yaml" node

作成されたtest.yamlの中身

--- 
? "Item 1"
: 
  ? "name"
  : >-
    kzfm

  ? "address"
  : >-
    xxx@gmail.com

  ? "password"
  : >-
    snail

これをperlでparseしてみる

use YAML;
my $filename = "test.yaml";
my $doc = YAML::LoadFile($filename);
print YAML::Dump($doc);

実行結果

---
Item 1:
  address: xxx@gmail.com
  name: kzfm
  password: snail

ナイス!

hoogleをローカルで

昨晩、String -> ByteStringに変換する関数がわかんね的なことをtweetしたらHoogeleで型検索出来ることを教えてもらった。

Hoogle 激ヤバ!マスト!!!!(ローカルに)

というわけで、ローカルで検索できるように

sudo cabal install hoogle

これだけ。

~/.cabal/binにhoogleっていうコマンドがインストールされるのでパス通しておく。

$ hoogle "String -> ByteString"
Data.ByteString.Char8 pack :: String -> ByteString
Data.ByteString.Lazy.Char8 pack :: [Char] -> ByteString
Prelude read :: Read a => String -> a
Text.Read read :: Read a => String -> a
Data.String fromString :: IsString a => String -> a
...

これはアンセムといっても間違いない。

Haskellのプログラムの中でエディタを使ってファイルをいじる

週末はニューラルネットの実装でもするつもりでいたのに、突然

Haskellのプログラムの中でファイルをエディットして保存したら、そのファイルの中身を読む

ということをやりたくなってしまった。要するにHaskellでこれがやりたくなった

import System.FilePath ((</>))
import System.Directory
import System.Process
import System.Environment
import Control.Monad (liftM)

main = do 
  home     <- getHomeDirectory
  (file:_) <- getArgs
  editor   <- liftM (lookup "EDITOR") getEnvironment
  case editor of Just ed -> (>>= waitForProcess) . runCommand $ ed ++ " " ++ (home </> file)
                 Nothing -> error "command error\n"
  inpStr <- readFile $ home </> file
  print inpStr

最初、

runCommand $ ed ++ " " ++ (home </> file)

って書いてて、あーブロックされてないんだろうなぁと。探したらどう書く?にあった。

あと、RWHのモナド変換子の章を読むべし的な流れになってる。

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

アッカーマン関数をHaskellで

計算論を読んでたらアッカーマン関数が出てたのでHaskellで書いてみた。

ack 0 n = n + 1
ack m 0 = ack (m-1) 1
ack m n = ack (m-1) $ ack m (n-1)

定義をそのまま書き下せばいい。

*Main> ack 1 2
4
*Main> ack 3 2
29
*Main> ack 3 4
125

それにしても計算論難しい。

ProductName 計算論 計算可能性とラムダ計算 (コンピュータサイエンス大学講座)
高橋 正子
近代科学社 / ¥ 3,570 ()
在庫あり。

Next Page