SlideShare una empresa de Scribd logo
1 de 31
Descargar para leer sin conexión
Haskell で CLI
@matsubara0507
新しくプログラミング言語を学んだ
ら何をするか?
コマンドを作りますね!
Agenda
1. コマンドライン引数
2. Alt. Prelude: RIO
3. Stack Template
コマンドライン引数
Haskell でコマンドライン引数
他にもたくさんあるけど、例えば
System.Environment.getArgs
System.Console.GetOpt
optparse-applicative
System.Environment.getArgs
base  パッケージにある関数
getLine  や  getEnv  のような他の IO 系と同じように扱
える
-- getArgs :: IO [String]
import System.Environment (getArgs)
main :: IO ()
main = do
args <- getArgs
print $ "Hi, " ++ head args
しかし,ただの空白区切
System.Console.GetOpt
これも  base  にある
getArgs  で得た文字列を特定の型に変換してくれる.
getOpt
:: ArgOrder a -- ^ non-opts な文字列の取り扱い方
-> [OptDescr a] -- ^ opts な文字列の扱い方
-> [String] -- ^ getArgs などで得た文字列
-> ([a], [String], [String])
返り値の型は  (オプションの型, non-opts な文字列, エラー)
(細かい説明は割愛)
System.Console.GetOpt  の使用例
import System.Console.GetOpt
main :: IO ()
main = do
args <- getArgs
let (opts, rest, err) = getOpt Permute options args
print opts
data Flag = Verbose | Version deriving (Show, Eq)
options :: [OptDescr Flag]
options =
[ Option ['v'] ["verbose"] (NoArg Verbose) "..."
, Option ['V'] ["version"] (NoArg Version) "..."
]
optparse-applicative
というパッケージ,よりリッチな事がたくさんできる
stack でも使われている(実質サンプル置き場)
少し使い方が難しいので,簡単にしたラッパーライブ
ラリがたくさんある
optparse­applicative­simple
optparse­generic
optparse­helper
optparse­simple
optparse-applicative  の使用例
import Options.Applicative
main :: IO ()
main = print =<< execParser options
where
opts = sample `withInfo` "Print a greeting for TARGET"
data Sample = Sample { hello :: String, verbose :: Bool }
sample :: Parser Sample
sample = Sample
<$> strOption ( long "hello" <> help ".." )
<*> switch ( long "verbose" <> short 'v' <> help ".." )
withInfo :: Parser a -> String -> ParserInfo a
withInfo opts = info (helper <*> opts) . progDesc
optparse-applicative  でサブコマンド
(おまけ話?本題?)
なんか ToDo タスクを処理できそうなサブコマンドの
型
data SubCmd
= NewCmd
| AddCmd Int Text
| DoneCmd Int
| ListCmd
deriving (Show, Eq)
optparse-applicative でサブコマンド
サブコマンドのパーサー
subcmdParser :: Parser SubCmd
subcmdParser = subparser
$ command "new" (pure NewCmd `withInfo` "...")
<> command "add" (AddCmd <$> ... `withInfo` "...")
<> command "done" (DoneCmd <$> ... `withInfo` "...")
<> command "list" (pure ListCmd `withInfo` "...")
hoge new  とか  hoge add  ってサブコマンドになる
Semigroup  の結合( <> )しかしてないんで網羅性チェッ
クは無理
拡張可能バリアントの導入
extensible というパッケージを使います
type SubCmd = Variant
'[ "new" >: ()
, "add" >: (Int, Text)
, "done" >: Int
, "list" >: ()
]
(extensible については wiki を参照してください)
拡張可能バリアントの導入
これで網羅性のチェックをしてくれるし、
ついでにサブコマンド文字列も自動で導出
subcmdParser :: Parser SubCmd
subcmdParser = variantFrom -- `variantFrom` 関数は自作
$ #new @= (pure () `withInfo` "...")
<: #add @= (... `withInfo` "...")
<: #done @= (... `withInfo` "...")
<: #list @= (pure () `withInfo` "...")
<: nil
詳しくは: オレ的 Haskell で CLI を作る方法 2018 ­
ひげメモ の extensible で optparse­applicative
拡張可能バリアントの導入
variantFrom ::
Forall (KeyIs KnownSymbol) xs =>
RecordOf ParserInfo xs -> Parser (Variant xs)
variantFrom = subparser . subcmdVariant
where
subcmdVariant =
hfoldMapWithIndexFor (Proxy @ (KeyIs KnownSymbol))
$ m x ->
let k = symbolVal (proxyAssocKey m)
in command k
((EmbedAt m . Field . pure) <$> getField x)
instance Wrapper ParserInfo where
type Repr ParserInfo a = ParserInfo a
_Wrapper = id
Alt. Prelude
Haskell の標準ライブラリ
(Haskell というか GHC というか)
base  という名前
Prelude というモジュールが標準インポート
NoImplicitPrelude  プラグマでオフにできる
標準ライブラリの代替
昔,Haskell­jp Slack で話題に上がった
slack­link (いずれなくなると思う)
classy­prelude
universum
rio
protolude
などなど
RIO ライブラリ
stack を開発しているチームが開発している
彼らのベストプラクティスをを詰め込んである
大域環境・ログ・エラーハンドリング
よく使うライブラリのラッパー
text ,  bytestring ,  directory ,  filepath
containers ,  lens ,  time ,  vector
などなど
RIO ライブラリの使用例
run :: RIO Env () -> Options -> IO ()
run cmd opts = do
token <- liftIO $ getEnv "MEDIUM_TOKEN"
logOpts <- logOptionsHandle stdout (opts ^. #verbose)
withLogFunc logOpts $ logger -> do
let env = #logger @= logger
<: #token @= fromString token
<: nil
runRIO env cmd
callMeAPI :: RIO Env ()
callMeAPI = do
logDebug "Run cmd: call me api"
token <- asks (view #token)
user <- API.getMe token
logDebug $ display ("get: " <> tshow user)
logInfo $ display ("Hi " <> user ^. #name <> "!!")
実行してみる
$ mdium --version
Version 0.2.0.0, Git revision
efcf1856b6b065141a6d366663b97b0301053ffd (23 commits)
$ mdium --verbose --me
2018-11-10 10:28:53.049919: [debug] Run cmd: call me api
@(src/Mdium/Cmd/Run.hs:57:3)
2018-11-10 10:28:54.721968: [debug] get: id @= "..." <:
username @= "nobutada" <: name @= "matsubara" <: url @=
"https://medium.com/@nobutada" <: imageUrl @= ".." <: nil
@(src/Mdium/Cmd/Run.hs:60:3)
2018-11-10 10:28:54.722133: [info] Hi matsubara!!
@(src/Mdium/Cmd/Run.hs:61:3)
Stack Template
Haskell Stack
Haskell のビルドツール
処理系自体は GHC
プロジェクト内の各パッケージのバージョン管理
などなど
$ stack new sample hoge-template
$ cd sample-project
$ stack build
$ stack exec -- application
stack new  の後がパターン化
stack new  した後に各基本的なコードが同じ
よく使うパッケージを  package.yaml  に追加
コマンドライン引数の処理する部分を追加
などなど
これを「オレオレテンプレート化」できる
自作テンプレートの例 (hsfiles)
{-# START_FILE package.yaml #-}
name: {{name}}
version: 0.1.0.0
homepage: https://github.com/{{github-username}}/{{name}}
...
dependencies:
- base >= 4.7 && < 5
- rio >= 0.1.1.0
- extensible >= 0.4.9
- yaml
...
{-# START_FILE app/Main.hs #-}
module Main where
import RIO
import Data.Extensible
...
公開できる!
今まではテンプレートファイルを特定のローカルパス
に置く必要があった.
stack­1.9 から GitHub, GitLab, BitBucket のリポジト
リから取得できる.
$ stack new sample github:matsubara0507/hoge.hsfiles
詳しくは: namespaced templates ­ BIG MOON
こんな感じ
おまけ: stack­tpls
matsubara0507/stack­tpls ­ GitHub
公開されているテンプレートを取得するコマンド
(まだ GitHub にしか対応していない...)
$ stack-tpls -l
github:commercialhaskell/chrisdone.hsfiles
github:commercialhaskell/foundation.hsfiles
github:commercialhaskell/franklinchen.hsfiles
github:commercialhaskell/ghcjs-old-base.hsfiles
github:commercialhaskell/ghcjs.hsfiles
github:commercialhaskell/hakyll-template.hsfiles
...
まとめ
コマンドライン引数の取得方法はいろいろ
単純なものからリッチなものまで
標準ライブラリや Prelude が微妙と思い始めたら
Alt. Prelude を探そう
オレオレプラクティスやパターンが出てきたらテ
ンプレート化しよう
(stack­tpls 使ってみて)
おしまい

Más contenido relacionado

La actualidad más candente

HashTable と HashDos
HashTable と HashDosHashTable と HashDos
HashTable と HashDos
Yuya Takeyama
 
Array twitter2
Array twitter2Array twitter2
Array twitter2
Jun Chiba
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
Shintaro Fukushima
 

La actualidad más candente (20)

[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
[TL06] 日本の第一人者が C# の現状と今後を徹底解説! 「この素晴らしい C# に祝福を!」
 
php7's ast
php7's astphp7's ast
php7's ast
 
HashTable と HashDos
HashTable と HashDosHashTable と HashDos
HashTable と HashDos
 
Everyday Life with clojure.spec
Everyday Life with clojure.specEveryday Life with clojure.spec
Everyday Life with clojure.spec
 
Array twitter2
Array twitter2Array twitter2
Array twitter2
 
200319 eash python_shareslide_functions
200319 eash python_shareslide_functions200319 eash python_shareslide_functions
200319 eash python_shareslide_functions
 
Applicative functor
Applicative functorApplicative functor
Applicative functor
 
CPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したいCPANの依存モジュールをもう少し正しく検出したい
CPANの依存モジュールをもう少し正しく検出したい
 
XMonad-oid on Emacs & More functional Emacs Lisp | 関数型LT大会
XMonad-oid on Emacs & More functional Emacs Lisp | 関数型LT大会XMonad-oid on Emacs & More functional Emacs Lisp | 関数型LT大会
XMonad-oid on Emacs & More functional Emacs Lisp | 関数型LT大会
 
PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門PHP5.5新機能「ジェネレータ」初心者入門
PHP5.5新機能「ジェネレータ」初心者入門
 
Stroustrup11章雑感
Stroustrup11章雑感Stroustrup11章雑感
Stroustrup11章雑感
 
Java SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイルJava SE 8 lambdaで変わる プログラミングスタイル
Java SE 8 lambdaで変わる プログラミングスタイル
 
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング(Ruby使いのための)Scalaで学ぶ関数型プログラミング
(Ruby使いのための)Scalaで学ぶ関数型プログラミング
 
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けープログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
プログラミング言語のパラダイムシフトーScalaから見る関数型と並列性時代の幕開けー
 
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
「Grails-1.1を斬る!〜Grails-1.1からのチーム開発〜」
 
Composable Callbacks & Listeners
Composable Callbacks & ListenersComposable Callbacks & Listeners
Composable Callbacks & Listeners
 
Local php-100828 2
Local php-100828 2Local php-100828 2
Local php-100828 2
 
Data processing at spotify using scio
Data processing at spotify using scioData processing at spotify using scio
Data processing at spotify using scio
 
Task
TaskTask
Task
 
データサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみるデータサイエンスワールドからC++を眺めてみる
データサイエンスワールドからC++を眺めてみる
 

Similar a Haskell で CLI

BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
Hiroshi Ono
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
Hiroshi Ono
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
Hiroshi Ono
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
博文 斉藤
 
Java8から始める関数型プログラミング
Java8から始める関数型プログラミングJava8から始める関数型プログラミング
Java8から始める関数型プログラミング
stylefreeslide
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
yoshiaki iwanaga
 
Scala2.8への移行
Scala2.8への移行Scala2.8への移行
Scala2.8への移行
guest5f4320
 

Similar a Haskell で CLI (20)

やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介やや関数型を意識した風Elixir/Phoenixご紹介
やや関数型を意識した風Elixir/Phoenixご紹介
 
PHP AST 徹底解説
PHP AST 徹底解説PHP AST 徹底解説
PHP AST 徹底解説
 
Start printf 6_takarakasai
Start printf 6_takarakasaiStart printf 6_takarakasai
Start printf 6_takarakasai
 
Scala on Hadoop
Scala on HadoopScala on Hadoop
Scala on Hadoop
 
from old Java to modern Java
from old Java to modern Javafrom old Java to modern Java
from old Java to modern Java
 
ScalaプログラマのためのHaskell入門
ScalaプログラマのためのHaskell入門ScalaプログラマのためのHaskell入門
ScalaプログラマのためのHaskell入門
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
BOF1-Scala02.pdf
BOF1-Scala02.pdfBOF1-Scala02.pdf
BOF1-Scala02.pdf
 
イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情イマドキの現場で使えるJavaライブラリ事情
イマドキの現場で使えるJavaライブラリ事情
 
asm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web gamesasm.js x emscripten: The foundation of the next level Web games
asm.js x emscripten: The foundation of the next level Web games
 
ゼロから始めるScala文法 (再)
ゼロから始めるScala文法 (再)ゼロから始めるScala文法 (再)
ゼロから始めるScala文法 (再)
 
GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法GNU awk (gawk) を用いた Apache ログ解析方法
GNU awk (gawk) を用いた Apache ログ解析方法
 
MapReduce入門
MapReduce入門MapReduce入門
MapReduce入門
 
Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7Pfi Seminar 2010 1 7
Pfi Seminar 2010 1 7
 
Project lambda
Project lambdaProject lambda
Project lambda
 
Java8から始める関数型プログラミング
Java8から始める関数型プログラミングJava8から始める関数型プログラミング
Java8から始める関数型プログラミング
 
第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」第三回ありえる社内勉強会 「いわががのLombok」
第三回ありえる社内勉強会 「いわががのLombok」
 
ECMAScript 6 Features(PDF 版)
ECMAScript 6 Features(PDF 版)ECMAScript 6 Features(PDF 版)
ECMAScript 6 Features(PDF 版)
 
Scala2.8への移行
Scala2.8への移行Scala2.8への移行
Scala2.8への移行
 

Más de Nobutada Matsubara

Más de Nobutada Matsubara (20)

Haskell で作る競技型イベントの裏側
Haskell で作る競技型イベントの裏側Haskell で作る競技型イベントの裏側
Haskell で作る競技型イベントの裏側
 
Marp Next Theme: Colors
Marp Next Theme: ColorsMarp Next Theme: Colors
Marp Next Theme: Colors
 
Marp Next Tips !
Marp Next Tips !Marp Next Tips !
Marp Next Tips !
 
貧者のための「cron」
貧者のための「cron」貧者のための「cron」
貧者のための「cron」
 
Build Dockferile with Haskell
Build Dockferile with HaskellBuild Dockferile with Haskell
Build Dockferile with Haskell
 
Elixir Programming with Type checking
Elixir Programming with Type checkingElixir Programming with Type checking
Elixir Programming with Type checking
 
MixML 作ってみる
MixML 作ってみるMixML 作ってみる
MixML 作ってみる
 
Elm でなんかつくる
Elm でなんかつくるElm でなんかつくる
Elm でなんかつくる
 
Haskell と Elm と JSON の話
Haskell と Elm と JSON の話Haskell と Elm と JSON の話
Haskell と Elm と JSON の話
 
ADVENTAR の Bot を作る with Haskell
ADVENTAR の Bot を作る with HaskellADVENTAR の Bot を作る with Haskell
ADVENTAR の Bot を作る with Haskell
 
Haskell Backpack 事始め
Haskell Backpack 事始めHaskell Backpack 事始め
Haskell Backpack 事始め
 
GitHub での Haskell の色が変わったんで
GitHub での Haskell の色が変わったんでGitHub での Haskell の色が変わったんで
GitHub での Haskell の色が変わったんで
 
日記って続かないよね...
日記って続かないよね...日記って続かないよね...
日記って続かないよね...
 
「7つの言語、7つの世界」を読む
「7つの言語、7つの世界」を読む「7つの言語、7つの世界」を読む
「7つの言語、7つの世界」を読む
 
Lisper はじめました (再)
Lisper はじめました (再)Lisper はじめました (再)
Lisper はじめました (再)
 
Haskell で LINE Bot を作ってみた
Haskell で LINE Bot を作ってみたHaskell で LINE Bot を作ってみた
Haskell で LINE Bot を作ってみた
 
Marp colors
Marp colorsMarp colors
Marp colors
 
Marp Tips
Marp TipsMarp Tips
Marp Tips
 
Whitespcae 入門
Whitespcae 入門Whitespcae 入門
Whitespcae 入門
 
入門 超絶技巧プログラミング !
入門 超絶技巧プログラミング !入門 超絶技巧プログラミング !
入門 超絶技巧プログラミング !
 

Haskell で CLI