基礎構文の組み合わせでIntを制限する(を教えてもらった)

nekoroll.hatenablog.com

f:id:nekorollykk:20200821161456p:plain
ガバガバだった

教えてもらいました


ellie-app.com

もうABAB↑↓BAさんに足向けて寝られないです
本当にありがとうございます

改めてやりたかったこと

  • Intだと広すぎる(-2147483647~2147483647)
    Basics - core 1.0.5
  • 2, -1, 1, 2のみを許容する型にしたい

この辺り勘違いしていて、-2~2を型として持とうとしていた

読み解く

type NumInCounter

type NumInCounter
    = One
    | Two

12のみを許容する型
マイナスは持たず数値だけを持つ
→足すか引くかはIncrement/Decrementの責務であって型が持つべきではない

だと思う(自信なし)

type Msg

-  = IncrementN Int

+  = Increment NumInCounter
+  | Decrement NumInCounter

N加算(減算)するのではなく
Increment/Decrement(加算/減算)で分けている

引数の型がIntから定義したNumInCounter(One, Two)に変更
これで加算/減算出来る数値の範囲がOne, Twoのみなっている

numIncCounterToInt関数

numInCounterToInt : NumInCounter -> Int
numInCounterToInt num =
    case num of
        One ->
            1

        Two ->
            2

定義した型NumInCounterIntに変換する関数
updateのIncrement/Decrement処理には数値が必要なので、ここで変換している
パターンマッチでOne, TwoVariantを網羅していて、
適当にThreeとか追加するとコンパイラが怒ってくれる(えらい)

Intだと濃度∞だけど
NumInCounterを定義してnumIncCounterToInt
パターンマッチを行っているので濃度2

update関数のパターンマッチ

-  IncrementN n ->
-      { model | count = model.count + n }

+  Increment num ->
+     { model | count = model.count + numInCounterToInt num }
+  Decrement num ->
+     { model | count = model.count - numInCounterToInt num }

nのチェックについてはnumInCounterToIntがやってくれているので安心
updateではIncrement/Decrementの加算減算を処理している

viewの変更

+  [ button [ onClick <| Increment One ] [ text "+1" ]
+  , button [ onClick <| Increment Two ] [ text "+2" ]
+  , button [ onClick <| Decrement One ] [ text "-1" ]
+  , button [ onClick <| Decrement Two ] [ text "-2" ]

これほんとすごくて
- One,Two(1,2)以外受け入れない様になっている
- 1 2ではなくOne, TwoなのでVariant命名次第では意味を持たせられる
counterサンプルだと微妙だけど、マジックナンバーがなくなる

ということがこれだけで実現できている
viewは加算 or 減算, 1 or 2を渡すだけになっている
分離がハッキリできている

まとめ

  • 関数に分離するという脳みそがなかった
  • 加算減算は型に持つべきじゃなくて、そこはupdate側の責務
  • あくまで型は入るべき値を定義するだけ

テクニック教えてもらって、凄いなー他にも色々あるのかなって思ったら

そう言われると確かに関数化してパターンマッチして組み合わせてるだけだった
基礎を覚えると応用がかなり効くElmすごい

久々に言語自体が面白くてワクワクしてている

次回

基礎的な構文を覚えたのでHtmlを色々出力してみる予定です
もうコツ掴んだし余裕っしょw
f:id:nekorollykk:20200821151703p:plain