The Elm Archtecture

type
とtype alias
の違いは?
type
type
がなんなのかはわかっていない。
使われ方としてはsealed class
に似ている気がする
type Either
= Loading
| Success { value: Int }
| Failure { message: String }
getValue : Either -> String
getValue either =
case either of
Loading -> "loading"
Success v -> "success"
Failure message -> "failure"
type alias
type alias
は型に名前をつけるもの
type alias T = { value: Int }

typeはカスタム型の宣言に利用するみたいだ
また別名がtagged unionやADTと呼ばれていることからseald classはあながち間違っていなそう

type alias
はレコードを作ってる
type alias T = { value : Int }
T // <function> : Int -> T
record : Int -> T
record first = { value = first }
record // <fucntion> : Int -> { value : Int }
typeAlias.elm
とtypeAliasLike.elm
はほぼほぼ同じ

type aliasはレコードを作る際に、コンストラクタを生成する

typeもtype aliasもコンストラクタは作ってそう
コード
type T
= A
| B String
| C String Int
a : T
a = A
b : String -> T
b = B
c : String -> Int -> T
c = C
type alias TA =
{
}
type alias TB =
{ a : String
}
type alias TC =
{ a : String
, b : Int
}
ta : TA
ta = TA
tb : String -> TB
tb = TB
tc : String -> Int -> TC
tc = TC

scalaでいうunapply?等を作ってくれるか作ってくれないかの違いはありそう
なんか違うかも?recordであれば以下で分解できる。
let {x, y} = position
variantならcase ofで分解?できる

エラーハンドリング
型にエラー情報を逃す。Result
やMaybe
でそれを実現する
Maybe
JavaのOption
と同等のものでnull
参照をなくす
type MaybeInt
= Value number
| Nothing
toInt : String -> MaybeInt
toInt string =
case String.toInt string of
Nothing -> Nothing
Just value -> Value value
Result
よく聞くEither
例外処理用の型
type Either value error
= Just value
| Err error

Variant
value
とすることでモデルを作ることができる

#コマンドとサブスクリプション
Html msg
でHTMLエレメントからメッセージを送るように、Cmd msg
でコマンドからメッセージを送れる。

Update関数の型定義とかとか

そもそもElm
が最大限生かされる書き方ってどんなんなんだろう?
MVCを深く知ると良いのかな??

Lens触ってみた。真価はわからない
import Html exposing (text)
import Monocle.Lens exposing (Lens, modify)
type alias User =
{ name : String
, age : Int
}
user : User
user = User "" 1
userNameLens : Lens User String
userNameLens =
let
get u = u.name
set n u = { u | name = n }
in
Lens get set
userAgeLens : Lens User Int
userAgeLens =
let
get u = u.age
set a u = { u | age = a }
in
Lens get set
increment : Int -> Int
increment value = value + 1
main = text (String.fromInt ((modify userAgeLens increment) user).age)

Extensible Record
参考

elmで依存関係の矯正ってできるっけ?

対象読者
- TypeScriptで型に触れ、型に興味を持った方
- 型の学習方法に迷っているTypeScriptユーザー
話すこと
- 型の濃度
- 型学習におけるElmや他の言語のすすめ
話さないこと
- ElmとTypeScriptの型の違い
結論
型のテクニックはTypeScriptだけではなく、他の言語から学べることがおおいので他の言語から学ぶのもおすすめします。
概要
プログラミングにおいて、型を集合として考える視点は非常に重要です。この記事では、Elmの例を通して、型を集合として捉える方法について解説します。さらに、TypeScriptでも同様のアプローチがあることを示します。
Elmにおける型と集合
まず、ElmにおけるCustomTypeを取り上げ、型を集合として理解する方法を探ります。CustomTypeは、複数の異なるケースを持つ型を定義する機能です。これにより、異なるデータの集合を一つの型として扱うことができます。
CustomTypeの例
type Program
= Raymonda
| LaSylphide Bool
このコードでは、Program
というCustomTypeが定義されています。この型には、RaymondaとLaSylphideの2つのバリアント※1があり、各バリアントは異なるデータを保持しています。
※1 バリアントとはカスタム型を構成する一つの値のことを指すと理解しています。TypeScriptに同等の使われ方がされるものは言語レベルではない気がします。同じ機能を有したものの再現はできます。
パターンマッチングによるCustomTypeの分解
Elmの強力な機能であるパターンマッチングを使えば、CustomTypeを分解して各バリアントにアクセスし、関連するデータを取り出すことができます。
choreographer : Program -> String
choreographer program = case program of
Raymonda -> "Marius Petipa"
LaSylphide isDenmark ->
if isDenmark then "Auguste Bournonville"
else "Filippo Taglioni"
この例では、Program型の各バリアントに応じて人名を返しています。
TypeAliasの例
また、type aliasを用いることで、単一のバリアントに対して型を定義することも可能です。ただし、type aliasはCustomTypeの代替ではありません。
type alias LaSylphide =
{ isDenmark : Bool
}
集合としての型
型を集合として捉えると、各型に「濃度」が存在することがわかります。濃度とは、集合に含まれる要素の数、すなわち型に対応するデータの数を指します。
Programの例では、RaymondaとLaSylphideという2つのバリアントがあり、それぞれ異なるデータの組み合わせを持っています。Raymondaはデータを持たないため濃度は1、一方、LaSylphideはBool型のデータを持ち、2つの組み合わせが可能です。したがって、Program型の濃度は合計で3です。
Programバリアント | データ | データ数 |
---|---|---|
Raymonda | - | 1 |
LaSylphide | true / false | 2 |
濃度の乗算
型の濃度は乗算することができます。乗算はバリアントが保持するデータ間で行われます。以下の例を見てみましょう。
type CustomUser = User Bool Bool
CustomUser型のUserバリアントは2つのBool値を持っています。各Bool値は2つの値(true/false)を取るため、CustomUserの濃度は4になります。
CustomUserバリアント | データ | データ数 |
---|---|---|
User | (true/false) (true/false) | 4 |
first boolean | second boolean |
---|---|
false | false |
false | true |
true | false |
true | true |
濃度の加算
型の濃度は、CustomTypeのバリアント間で加算できます※2。以下の例を考えてみましょう。
type Color
= Red
| Yellow
| Blue
Color型は、Red、Yellow、Blueの3つのバリアントで構成され、それぞれデータを持たないため、Colorの濃度は3です。
Colorバリアント | データ | データ数 |
---|---|---|
Red | - | 1 |
Yellow | - | 1 |
Blue | - | 1 |
※2 厳密には和の計算が行わえるのはCustomTypeの濃度だけではなく、TypeAliasやタプルでも和の計算が行われます。
濃度の意識の重要性
濃度を意識して型設計を行うことは、不要なパターンを排除し、コードをより明確にするために重要です。たとえば、ロード状態を表すデータ型を考えてみましょう。
type LoadingState a
= Loading
| Loaded a
このLoadingState型の濃度は一番少なくて2です。
LoadingStateバリアント | データ | データ数 |
---|---|---|
Loading | - | 1 |
Loaded | a | aのデータ数※3 |
次に、type aliasを使って同じ概念を表現してみます。
type alias LoadingState a =
{ isLoading : Bool
, data : Maybe a
}
この場合、濃度は最低でも4になります。
isLoading | data |
---|---|
false | Nothing |
false | Just a |
true | Nothing |
true | Just a |
このように、type aliasを使うと不要なデータの組み合わせが増え、処理の複雑さが増してしまいます。これは型の濃度を意識しなかった結果、濃度の乗算が行われているからです。
display : (a -> String) -> LoadingState a -> String
display toString loadingState =
case loadingState.data of
Nothing ->
if loadingState.isLoading then
"Loading"
else
"Loaded ? Nothing ?"
Just value ->
if loadingState.isLoading then
"Loading ? Loaded ?"
else
String.join " " ["Loaded", toString value]
これに対し、CustomTypeを正しく設計することで、この問題を避けることができます。CustomTypeを使って再実装します。
display : (a -> String) -> LoadingState a -> String
display toString loadingState =
case Loading -> "Loading"
case Loaded value -> String.join " " ["Loaded", toString value]
※3 Elmにおいて型定義に出てくる小文字は任意の型を表します。なのでこの表ではaのデータの数はわからないです。そのため数値ではなくaのデータ数と表記しています。
TypeScriptとCustomType
Elmに存在するCustomTypeは、TypeScriptでもDiscriminated Unionというテクニックとして利用できます。Elmや他の言語で学んだ型のテクニックは、TypeScriptで同様に再現可能です。※4 さらに、Elmや他の言語で使用されている多くの型のテクニックをTypeScriptに輸入して活用することができます。
たとえば、Branded Typeは、Elmや他の言語が以前から持っていた技術であり、TypeScriptでも活用されています。
したがって、型に関する知識を深めるためには、TypeScript以外の言語からも学ぶことが有益です。その第一歩として、Elmを使ってみるのはいかがでしょうか。
※4 全部ではない。ただし大抵の事はできそう。現に型レベルでの四則演算やHKTなどの抽象度の高い型などの再現はできている。
まとめ
この記事では、プログラミングにおける型を集合として捉える視点が、どのように型設計に影響を与えるかを探りました。特に、ElmのCustomTypeを例に、型が持つデータの組み合わせ(濃度)を理解することの重要性を解説しました。型の濃度を意識することで、無駄なパターンを排除し、シンプルで明確なコードを設計することが可能になります。
また、TypeScriptでもElmのような型のアプローチを再現できることを示し、他の言語で培った型の技術をTypeScriptに輸入できることについても触れました。Elmを通じて型を学んでみたいと思った方は是非ガイドラインを見てElmを始めてみてください。
参考文献