てっしーの雑記

主に技術系のネタを

Elm 言語メモ

ElmArchitectureを始めたのですが、基本言語仕様が頭に入っておらず動いているソースをみても「この書き方って結果どうなるの?」でググることが多いので自分メモで整理したいと思います
いろんなサイトから写経させていただいた自分メモ用なので読み飛ばしてもらってOKです^^;

参考:Elmのシンタックス - Galapagos Blog

リテラル

> 'a'
'a' : Char

> "HelloWorld!"
"HelloWorld!" : String

> True
True : Bool
> False
False : Bool

> 1000
1000 : number

> 1.0
1 : Float

> (1, "abc")
(1,"abc") : ( number, String )      -- Tuple

> [1, 2, 3]
[1,2,3] : List number       -- List

Elmでの関数

  • 同じ引数に対して同じ結果を返す
  • 引数の状態を変えてはいけない
  • Elmはイミュータブルな世界なので変えられない

関数

add : Int -> Int -> Int
add x y =
    x + y
  • add関数
  • Int -> Int -> Int引数 -> 引数 -> 戻り値 を意味する

無名関数

\x y -> x + y
  • 先頭に \ をつける
  • 上記は引数2つを受け取り、足した結果を返す

引数なし関数

name : String
    "Taro"
  • 定数となる

グループ化

  • 関数の結果を別の関数の引数に渡したい場合に () を使う
  • グループ化しなと multiply が addの引数とみなされてしまう
multiply :Int -> Int -> Int
multiply x y =
    x * y

add 3 (multiply 1 2)  -> 5
  • パイプ演算子を利用すると見やすくすることができる
add 3 <| multiply 1 2   -> 5

2 |> multiply 1 |> add 3  -> 5
  1. 1 を multiply の第一引数に渡す
  2. 2 を multiply の第二引数に渡す
  3. multiply の結果を add の第一引数に渡す
  4. 3 を add の第二引数に渡す

パイプオペレータ

2 |> power
-- 左から右へ渡す

power <| 2
-- 右から左へ渡す

関数の応用

関数が引数

funcArg: (Int -> Int) -> Int -> Int
funcArg func x = 
    func xa

-- 利用方法
funcArg (\x -> 2 * x) 2

関数が戻り値

funcReturn : (int -> Int)
funcReturn =
    \x -> 2* x

-- 利用方法
func = funcReturn
func 2

type alias

  • 型に別名をつける
func :String -> String -> Int

-- 上よりも下のほうがわかりやすく堅牢

type alias Id = String
type alias Name = String
func : Id -> Name -> Int

再帰定義

  • 型を再帰的に利用することができる
type Human = human
    {
        id : Int
        , name:String
        , sex: Int
        , birthday: String
        , father: human
        , mother:human 
    }

or

type alias Human =
    {
        id : Int
        , name:String
        , sex: Int
        , birthday: String
        , father: InHuman
        , mother: InHuman 
    }
type InHuman = InHuman Human

Union Type

  • 複数の定数を1つの型で使えるようになる
  • Enumみたいなもの
  • | でつなぐ
type Result = Ok | Ng

checkResult result =
    case result of
        Ok -> True
        Ng -> False

checkResult Ok --> True
checkResult Ng --> False

Recodes

  • Key : Valueのセットを持つ
  • イミュータブルなので変更するには新しいレコードを作る必要がある
type alias User =
    {id : Int, name : String}

user =
    User 1 "taro"

user.id --> 1
user.name --> "taro"

newUser = 
    {user | name = "jiro"}

Listの関数

filter

  • 判定方法を実装した関数とListを渡すと、判定結果を満たしたListを返す
List.filter (\x -> x % 2 == 0) [1, 2, 3] --> 結果[2]

map

  • 変換方法を実装した関数とListを渡すと、List要素すべてに関数を適用したListを返す
List.map (\x -> x * 2) [1, 2, 3] --> 結果[2, 4, 6]

Maybe

  • Java8の Optional と同じ
  • あり -> Just
  • なし -> Nothing
type Maybe a
    = Just a
    | Nothing
Just 1

map

  • 変換方法を実装した関数とMaybeを渡すと Justの場合は、関数で変換 Nothingの場合は、なにもしない
Maybe.map (\x -> toString x) Just 1 -> "1"
Maybe.map (\x -> toString x) Nothing -> Nothing

withDefault

  • デフォルト値とMaybeを渡すと Justの場合は、要素を取り出す Nothingの場合は、デフォルト値を返す
Maybe.withDefault 0 <| Just 1 --> 1
Maybe.withDefault 0 Nothing  -- 0

構文

if

  • if文ではなく式なので評価された値を返す
  • elseは必須で省略はできない
if True then "a" else "b"

[結果] "a"

if Flase then
    "b"
else
    "a"

[結果]"b"

count = 1
if count < 0 then
    "less then zero"
else if count == 0 then
    "equal zero"
else
    "over zero"

[結果] "over zero"

case

_ は多言語のdefaultと同じ

case [式] of
    [条件] -> [結果]
    _ -> [結果]

if同様に式なため評価結果を返す

level = 99
case level of
    1 -> "Level min"
    99 -> "Level max"
    _ -> "Other Level"

[結果]"Level max"

let

  • 値を変数に入れて使うことができる
let
    a = 1 + 1

    (b, c) = (2, 3)
in
    a * b * c

-> 12

再帰

  • ループはない
  • Collection系に定義されている関数を使うか再帰を使う
sum : List Int -> Int
sum list =
    case list of
        [] ->
            0
 
        x :: xs ->
            x + sum xs
sum [] --> 0
sum [1, 2, 3] --> 6

モジュール

  • モジュール=ファイル
  • モジュール名はファイル名と一致している必要がある ** Common.StringUtils なら Common/StringUtils.elm

宣言

-- すべて公開
module Hoge exposing (..)
-- 一部公開
module Hoge exposing (func,fuga(..))

import

import Hoge
Hoge.func

-- 別名
import Hoge as hoge
hoge.func

-- 直接
import Hoge exposing(func)
func

デフォルトimport

  • 以下はデフォルトで読み込まれているので宣言不要
import Basics exposing (..)
import Debug
import List exposing ( List, (::) )
import Maybe exposing ( Maybe( Just, Nothing ) )
import Result exposing ( Result( Ok, Err ) )
import Platform exposing ( Program )
import Platform.Cmd exposing ( Cmd, (!) )
import Platform.Sub exposing ( Sub )