Haskell初心者が電卓アプリを作る : 1

電卓アプリには以下の要素が含まれており、どんな言語でも初学者の練習に向いているように思います。

  1. 状態の管理、遷移
  2. 計算中の値の保持、更新 (副作用)
  3. 文字列と数値の相互変換 (型の違い)
  4. イベントハンドラ

Haskell においては、特に 2 と 3 は言語的に強い制限がかけられているので、それをどう解決するかを知るのに適していると思います。Haskell 初心者の私が実装した体験と感想を、それ辺りをふまえて書きたいと思います。

本記事では電卓アプリの仕様についてのみ記載するので、練習や研修に使ってください。コードについては次回以降の記事に記載します。

アプリ概要

卓上電卓を再現したアプリを作成します。画像の赤枠の部分の要素と機能を有するものとします。

UIの要素について

表示画面

  • 入力中の数値や計算結果の数値を表示する
  • 最大12桁表示できる

数字キー

  • 0 ~ 9 キーと 00 キー
  • 数字を入力する

プラスマイナスキー

  • +/- キー
  • 表示中の数字の + / – を入れ替える

ドットキー

  • . キー
  • 小数点以下を入力するときに用いる

演算キー

  • +, -, ×, ÷ キー
  • 行う演算を指定する

イコールキー

  • = キー
  • 計算を実行する

Cキー

  • 現在の入力値をクリアする

ACキー

  • 全てをクリアする

機能について

電卓アプリは以下の 4 つの状態を持ち、それぞれの状態において各キーの動作が異なります。

  1. 第 1 変数入力 (FirstInputStep)
    • 計算する 1 番目の数を入力する状態のこと。
    • 演算子を選択すると演算子選択後状態に遷移する。
  2. 演算子選択後 (OperationSelectedStep)
    • 演算子を決定した直後の状態のこと。
    • 表示画面には第 1 変数を表示する。
    • 演算子の押し間違いを訂正できる。
    • この状態では第 1 変数の変更をできない。数字を入力した時点で第 2 変数入力状態に遷移する。
  3. 第 2 変数入力 (SecondInputStep)
    • 計算する 2 番目の数を入力する状態のこと。
    • イコールキーを押下すると、第 1 変数と第 2 変数、演算子をもとに計算し、結果表示状態に遷移する。
  4. 結果表示 (ResultStep)
    • 計算結果を表示する状態のこと。
    • 演算子を選択することで、計算結果を第 1 変数として引き続き計算を行うことができる。
    • 計算結果を変更することはできない。数字を入力した時点で第 1 変数入力状態に遷移する。

それぞれの状態において、各キーの動作は以下のようになります。

数字キー

  1. 第 1 変数入力状態
    • 表示されている数字の末尾に、押下した数字を追加する。
    • ただし表示されている数字が “0” の場合は押下した数字を表示する (00は0と同じ扱い)。
  2. 演算子選択後状態
    • 表示を押下した数字に変更し (00は0と同じ扱い)、第 2 変数入力状態に遷移する
  3. 第 2 変数入力状態
    • 第 1 変数入力状態と同様。
  4. 結果表示状態
    • 表示を押下した数字に変更し (00は0と同じ扱い)、第 1 変数入力状態に遷移する。

プラスマイナスキー

  1. 第 1 変数入力状態
    • 表示されている数字の符号を変える。
    • 表示されている数字が “0” の場合は変更しなくて良い。
  2. 演算子選択後状態
    • 表示を “0” に変更し、第 2 変数入力状態に遷移する
  3. 第 2 変数入力状態
    • 第 1 変数入力状態と同様。
  4. 結果表示状態
    • 表示を “0” に変更し、第 2 変数入力状態に遷移する

ドットキー

  1. 第 1 変数入力状態
    • 表示されている数字に小数点がない場合、末尾に小数点を付与する。
    • 表示されている数字に小数点がある場合、何もしない。
  2. 演算子選択後状態
    • 表示を “0.” に変更し、第 2 変数入力状態に遷移する。
  3. 第 2 変数入力状態
    • 第 1 変数入力状態と同様。
  4. 結果表示状態
    • 表示を “0.” に変更し、第 1 変数入力状態に遷移する。

演算キー

  1. 第 1 変数入力状態
    • 押下した演算子と入力されている数字を (第 1 変数として) 保持する。
    • 演算子選択後状態に遷移する。
    • 表示は変更しない。
  2. 演算子選択後状態
    • 保持している演算子を押下した演算子に置き換える。
  3. 第 2 変数入力状態
    • 第 1 変数と入力されている数字を、保持している演算子に従って計算し、計算結果を表示する。
    • 押下した演算子を保持する。
    • 演算子選択後状態に遷移する。
  4. 結果表示状態
    • 押下した演算子と入力されている数字を (第 1 変数として) 保持する。
    • 演算子選択後状態に遷移する。
    • 表示は変更しない。

イコールキー

  1. 第 1 変数入力状態
    • 何もしない
  2. 演算子選択後状態
    • 何もしない
  3. 第 2 変数入力状態
    • 第 1 変数と入力されている数字を、保持している演算子に従って計算し、計算結果を表示する。
    • 結果表示状態に遷移する。
  4. 結果表示状態
    • 何もしない

Cキー

  1. 第 1 変数入力状態
    • 表示を “0” にする。
  2. 演算子選択後状態
    • 保持している値、演算子を全て破棄し、表示を “0” にし、第 1 変数入力状態に遷移する。
  3. 第 2 変数入力状態
    • 表示を “0” にする。
  4. 結果表示状態
    • 表示を “0” にし、第 1 変数入力状態に遷移する。

ACキー

  1. 第 1 変数入力状態
    • 表示を “0” にする。
  2. 演算子選択後状態
    • 保持している値、演算子を全て破棄し、表示を “0” にし、第 1 変数入力状態に遷移する。
  3. 第 2 変数入力状態
    • 保持している値、演算子を全て破棄し、表示を “0” にし、第 1 変数入力状態に遷移する。
  4. 結果表示状態
    • 表示を “0” にし、第 1 変数入力状態に遷移する。