HaskellのCSV読み込み
利用ライブラリ
インポート
Prelude> import Text.CSV
1行読み込み
Prelude Text.CSV> parseCSVTest "aaa,bbb" [["aaa","bbb"]] Prelude Text.CSV> parseCSVTest "aaa,bbb,ccc" [["aaa","bbb","ccc"]]
トリムはしない
Prelude Text.CSV> parseCSVTest "aaa,bbb, ccc" [["aaa","bbb"," ccc"]]
複数行読み込み
Prelude Text.CSV> parseCSVTest "aaa,bbb, ccc\naaa," [["aaa","bbb"," ccc"],["aaa",""]] Prelude Text.CSV> parseCSVTest "aaa,bbb, ccc\naaa,,bbb" [["aaa","bbb"," ccc"],["aaa","","bbb"]]
出力
Prelude Text.CSV> printCSV [["1","2","3"],["4","5"],["6"]] "\"1\",\"2\",\"3\"\n\"4\",\"5\"\n\"6\""
読み込み件数取得
Prelude Text.CSV> parseCSVFromFile "./data/UNdata_Export_pork.csv" >>= \x -> either (\x -> return 0) (return . length) x 1376
10行目出力
Prelude Text.CSV> parseCSVFromFile "./data/UNdata_Export_pork.csv" >>= \x -> return $ either (\x -> []) (\x -> x !! 10) x ["Albania","2009","Thousand metric tons","0.63",""]
全件出力
Prelude Text.CSV> either (\x -> putStrLn "error") (mapM_ (putStrLn . show)) =<< parseCSVFromFile "./data/UNdata_Export_pork.csv" ["Country or Area","Year","Unit","Value","Value Footnotes"] ["Albania","2013","Mil. USD","3.86207176515949",""] ["Albania","2013","Thousand metric tons","0.8",""]
ServantのFileUploadサンプル
package
servant-multipart: multipart/form-data (e.g file upload) support for servant
$ cabal install servant-multipart Resolving dependencies... Notice: installing into a sandbox located at foo/.cabal-sandbox Downloading http-client-0.5.6.1... Configuring natural-transformation-0.4... Configuring http-client-0.5.6.1... Building natural-transformation-0.4... ...
sample
client
$ curl -i -X PUT http://127.0.0.1:8081/file -F "upfile1=@MyWebApp_upload.hs" -F "xx=yy" HTTP/1.1 100 Continue HTTP/1.1 200 OK Transfer-Encoding: chunked Date: Tue, 14 Mar 2017 12:03:05 GMT Server: Warp/3.2.9 Content-Type: application/json;charset=utf-8 {"msg":"\"upfile doesn't exist\"","len":-1} $ $ curl -i -X PUT http://127.0.0.1:8081/file -F "upfile=@MyWebApp_upload.hs" -F "xx=yy" HTTP/1.1 100 Continue HTTP/1.1 200 OK Transfer-Encoding: chunked Date: Tue, 14 Mar 2017 12:03:13 GMT Server: Warp/3.2.9 Content-Type: application/json;charset=utf-8 {"msg":"uploaded","len":1633} $ ls -al MyWebApp_upload.hs -rw-r--r-- 1 foo bar 1633 3 4 11:01 MyWebApp_upload.hs $
server log
*Main> main FileData {fdInputName = "upfile1", fdFileName = "MyWebApp_upload.hs", fdFileCType = "application/octet-stream", fdFilePath = "/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/servant-multipart1974930991404280278.buf"} not exist FileData {fdInputName = "upfile", fdFileName = "MyWebApp_upload.hs", fdFileCType = "application/octet-stream", fdFilePath = "/var/folders/hw/p4bp49hd7v9_1j60sjvmhqnr0000gn/T/servant-multipart8933518161505795335.buf"}
HaskellでYamlの任意項目の取り扱い
Applicative
スタイルで.*?
で任意項目、.!=
でデフォルト値を設定します。`
parseJSON (Object m) = AppConfig <$> m .:? "port" .!= 8081 -- default
ghciのプロンプトをいい感じにする方法
いつも忘れるので備忘
>:set prompt "\ESC[34mλ> \ESC[m" λ> aa <interactive>:28:1: error: Variable not in scope: aa λ> :set prompt "\ESC[1;34m%s\n\ESC[0;34mλ> \ESC[m" *Main Control.Monad.Morph Control.Monad.Trans Control.Monad.Trans.Maybe Control.Monad.Trans.State
tidalをreplから使う
1: SuperColliderを起動する。
2: SuperDirtを起動する。
SuperDirt.start;
3: ghciを起動、ライブラリの取り込み
$ cabal repl GHCi, version 8.0.1: http://www.haskell.org/ghc/ :? for help Prelude> import Sound.Tidal.Context -- インポート
4: repl上でコーディングする
Prelude Sound.Tidal.Context> :t bpsUtils -- 時間を取得する bpsUtils :: IO (Double -> IO (), IO Rational) Prelude Sound.Tidal.Context> let s = bpsUtils Prelude Sound.Tidal.Context> :t superDirtSetters -- パターン関数を取得する superDirtSetters :: IO Time -> IO (ParamPattern -> IO (), (Time -> [ParamPattern] -> ParamPattern) -> ParamPattern -> IO ()) Prelude Sound.Tidal.Context> let dd = s >>= \x -> superDirtSetters (snd x) Prelude Sound.Tidal.Context> :t sound sound :: Pattern String -> ParamPattern Prelude Sound.Tidal.Context> :t atom atom :: a -> Pattern a Prelude Sound.Tidal.Context> :t sound . atom -- 文字列からパターンを作成する sound . atom :: String -> ParamPattern Prelude Sound.Tidal.Context> dd >>= \x -> fst x (sound (atom "bd")) -- バスドラが鳴る
(solved) The pkg-config package 'libpcre' is required but it could not be found.
pkg-confg
として認識されているか確認する。
$ pkg-config --libs libpcre Package libpcre was not found in the pkg-config search path. Perhaps you should add the directory containing `libpcre.pc' to the PKG_CONFIG_PATH environment variable No package 'libpcre' found
profile
の編集
$ vim ~/.bash_profile
.bash_profile
に下記を追加。
export PKG_CONFIG_PATH=/usr/lib/pkgconfig
パスを登録
source ~/.bash_profile
認識されていることを確認
$ pkg-config --libs libpcre -lpcre
再インストール
$ cabal install pcre-light-0.4.0.4 --reinstall Resolving dependencies... In order, the following will be installed: pcre-light-0.4.0.4 (via: mysql-simple-0.4.0.1) (new version) mysql-simple-0.4.0.1 (via: persistent-mysql-2.6) (reinstall) (changes: pcre-light-0.4.0.3 removed) persistent-mysql-2.6 (reinstall) (changes: mysql-simple-0.4.0.1 removed) Warning: Note that reinstalls are always dangerous. Continuing anyway... Notice: installing into a sandbox located at /work03/webapp/servant04/.cabal-sandbox Configuring pcre-light-0.4.0.4... Building pcre-light-0.4.0.4... Installed pcre-light-0.4.0.4 Configuring mysql-simple-0.4.0.1... Building mysql-simple-0.4.0.1... Installed mysql-simple-0.4.0.1 Configuring persistent-mysql-2.6... Building persistent-mysql-2.6... Installed persistent-mysql-2.6 Updating documentation index /work03/webapp/servant04/.cabal-sandbox/share/doc/x86_64-osx-ghc-8.0.1/index.html
ServantのFormサンプル
POST
でForm
データを送信するServant
の実装サンプルを、本家サイトも含めて探していたのですが、見つけられませんでした。結果的にはとっても簡単でした。FromForm
のインスタンスにするだけでした。
data Res = Res { ret :: Int} deriving (Eq, Show, Generic) -- Formデータを受け取るデータ構造 instance FromForm Req --- FromFormのインスタンスにする。
実行
$ curl -w '\n' 'http://localhost:8081/add' --data 'x=1&y=1' -XPOST {"ret":2}
送信したデータの型が不正の場合は400
となる。
$ curl http://127.0.0.1:8081/add -d "x=1&y=a" -XPOST could not parse: `a' (input does not start with a digit)