第1回daab勉強会 発表

Yuji Yamamoto (山本悠滋)

2018-07-13

はじめまして! (^-^)

宣伝 hask(_ _)eller

今日のテーマ

メッセージ送信どうしてる?

今日のテーマ

メッセージ送信どうしてる?
 __∧______
(Haskellで!)

今日話すこと

おことわり hask(_ _)eller

🤔課題:

例: おなじみ「日報bot」

例: おなじみ「日報bot」

その現実

何が問題?

daab だと

こんな感じ?

// ユーザーごとの状態を管理する連想配列
const statusByUser = {};

// ユーザーごとの状態を表すenum的なもの
const LISTENING_JOBS = 0;
const LISTENING_ACHIEVEMENT = 1;

daab だと

こんな感じ?

// 「報告」と発言したユーザーの状態を更新
robot.respond(/報告/, (res) => {
    statusByUser[res.message.user.name] = LISTENING_JOBS;
    res.replay("今日はどんな業務をしましたか?");
});

daab だと

こんな感じ?

// 業務を報告したユーザーの業務を追加
robot.respond(/.*/, (res) => {
    const user = res.message.user.name;
    if (statusByUser[res.message.user.name] === LISTENING_JOBS){
        logJob(user, res.match[0]);
    };
    // ...
});

daab だと

こんな感じ?

// 「。」と発言したユーザーに達成度を尋ねる
robot.respond(/。/, (res) => {
    if (statusByUser[res.message.user.name] === LISTENING_JOBS){
        statusByUser[res.message.user.name] = LISTENING_ACHIEVEMENT;
    }
    res.send({
        question: "達成度はどれくらいですか?",
        options: [/* ... */]
    });
});

daab だと

direct-hs だと

※詳しくはこちら
※抜粋した上で、本質的でない部分を削っています。雰囲気だけ感じ取ってください。

-- 「報告」を含むメッセージを受け取ったら
-- 「Channel」を通したユーザーとの会話を始める
handleCreateMessage client (D.Txt txt)
  | "報告" `T.isInfixOf` txt =
    forkIO (D.withChannel client nippo)

direct-hs だと

全体の流れが把握しやすい!

nippo chan = do
    jobs <- askJobs       -- 業務を尋ねて
    logJobs jobs          -- 業務を記録して
    eval <- askEvaluation -- 評価を尋ねて
    logEvaluation eval    -- 評価を記録して
    bye                   -- さようならの挨拶

direct-hs だと

-- 業務を訪ね始める
askJobs = do
    D.send chan (D.Txt "今日はどんな業務をしましたか?")
    askJobsLoop []

direct-hs だと

-- 業務を訪ね始める
askJobsLoop jobs = do
    -- 「Channel」に紐付いた相手からのメッセージだけを受信
    msg <- D.recv chan

    -- 「。」と相手が回答するまで尋ね続ける
    case msg of
        D.Txt "。" -> return jobs
        D.Txt job  ->
            askJobsLoop (job:jobs)

direct-hs だと

-- 評価を記録し始める
askEvaluation = do
    D.send chan (D.SelectQ "達成度はどれくらいですか?" ["100","50","0"])
    recvLoop

direct-hs だと

recvLoop = do
    msg <- D.recv chan

    -- 数値を選んだときのメッセージ以外はエラー
    case msg of
      D.SelectA _ _ ans -> return ans
      _                 -> do
          D.send chan (D.Txt "数値を選んでください。")
          recvLoop

direct-hs だと

bye = D.send chan (D.Txt "気をつけてお帰りください。")

direct-hs だと

仕組み

wake wordを受け取る前

仕組み

誰かからwake wordを受け取った時

仕組み

誰かからwake wordを受け取った後

所感

おことわり

その他、JavaScriptではできなくてHaskellだからできたこと

メッセージにちゃんと型をつけたよ!

おまけ

direct4bコマンドを作りました。
シェルスクリプトなどに組み込んで使うことを想定しています。

インストール例・使用例(要: Stack

$ git clone https://github.com/iij-ii/direct-hs.git
$ stack install
$ echo こんにちは、世界! | direct4b -- send <TALK_ID>

まとめ