lue-bird / elm-keysset / Map

Map content inside a nested structure


type alias Mapping unmapped mapTag mapped =
Typed Typed.Checked mapTag Typed.Public (unmapped -> mapped)

Typed change

To create, combine

-- module Game exposing (Score, score)

type alias Game =
    { ..., score : Int }

type Score
    = Score

score : Mapping Game Score Int
score =
    Map.tag Score .score

To "nest" Mappings typed-value has some powerful helpers:

-- module String.Map exposing (each, Each, ToList, toList)
type ToList
    = ToList

toList : Mapping String ToList (List Char)
toList =
    Map.tag ToList String.toList

type Each
    = Each

each :
    Mapping element elementMapTag elementMapped
    -> Mapping (List element) ( Each, elementMapTag ) (List elementMapped)
each elementMapping =
    Typed.mapToWrap Each List.map elementMapping

There's nothing more to it

Use [Alter] if unmapped and mapped types are the same


type alias Altering subject alterTag =
Mapping subject alterTag subject

Mapping that will preserve the element type.

Altering can be used to simplify argument and result types

-- module User.Map exposing (onHead)

import Map

type alias User =
    { name : String, ... }

type Name
    = Name

name : Altering String nameAlterTag -> Altering User ( Name, nameAlterTag )
name =
    Typed.mapToWrap Name (\f user -> { user | name = user.name |> f })

This applies to records, types without any type variables or mapping some of many equal-typed elements

create

tag : tag -> (a -> b) -> Mapping a tag b

Create a uniquely tagged Mapping for a given function a -> b.

identity : Altering subject_ Identity

Returns what comes in without changing anything

"please edit"
    |> Map.with Map.identity
--> "please edit"


type Identity

Opaque tag for identity

combine

over : Mapping mapped nextMapTag nextMapped -> Mapping unmapped structureTag mapped -> Mapping unmapped (Over structureTag nextMapTag) nextMapped

Transform elements as shown in a given Mapping with a given function

import Typed

type Book
    = Book

book : Mapping { book : { sales : Int } } Book { sales : Int }
book =
    Typed.tag Book .book

type Sales
    = Sales

sales : Mapping { sales : Int } Sales Int
sales =
    Typed.tag Sales .sales

{ book = { sales = 0 } }
    |> Map.with (book |> Map.over sales)
--> 0


type alias Over mapTag nextMapTag =
( OverTag, ( mapTag, nextMapTag ) )

Tag for over


type OverTag

Wrapper tag in Over

transform

with : Mapping unmapped mapTag_ mapped -> unmapped -> mapped

Apply the given change

import Typed

[ 'h', 'i' ]
    |> Map.with (Typed.tag { whatever = () } String.fromList)
--> "hi"