andre-dietrich/elm-generic/1.0.0

NOTE: the latest version is 2.0.0

Generic

This module defines a basic type system, as it is known from JavaScript. The basic idea is that you can use generic types of decoders that can translate into this format, so you are not forces anymore to write custom decoders if your are only interested in some basic values.

The type system should also behave similarly the one we know from JavaScript.

Types

type Value
= Null
| Bool Bool
| Int Int
| Float Float
| String String
| List (List Value)
| Set (EverySet Value)
| Dict (Dict Value Value)
| Date Posix
| DateTime Posix

Supported basic types. In contrast to JSON types, this covers also types such as Set, Date, and DateTime.

In the future it would also be interesting to have a general binary type that can be used with any kind of transformation function, i.e. toFloat or for serializing streams of data (lists, sets, etc.).

Sets and Dicts use different types than the Base elm-types, so that they can cope with more complex values that Int, String, etc. Thus, a Generic.Dict can also have keys of type integer or list, nested ones are also allowed.

typeOf : Value -> String

Clone of the JavaScript function typeof that returns a String:

typeOf Null --> "null"


typeOf (Bool True) --> "bool"


typeOf (Int -99) --> "int"


typeOf (Float 1.234) --> "float"


typeOf (String "foo") --> "string"

Getting & Setting

get : List Value -> Value -> Maybe Value

Generic getter, the first parameter defines a sequence of how the generic type should be traversed. The result is a Maybe Value that needs to be converted into your desired elm-type:

import Generic.Decoder exposing (decode)


"{\"type\": [1, [2, \"tada\"] ]}"
    |> decode
    |> Result.withDefault Null
    |> get [String "type", Int 1, Int 1]
    |> Maybe.andThen toString
    |> (==) (Just "tada") --> True


"{\"type\": [1, [2, \"tada\"] ]}"
    |> decode
    |> Result.withDefault Null
    |> get [Int 99]
    |> Maybe.andThen toString
    |> (==) Nothing --> True
set : List Value -> Value -> Value -> Value

Generic setter, the first parameter defines a sequence of how the generic type should be traversed and the second the new value

import Generic.Json as Json
import Generic as Gen


"{\"type\": [1, [2, \"tada\"] ]}"
    |> Json.decodeString
    |> Gen.set [Gen.String "type", Gen.Int 1, Gen.Int 1] (Gen.Int 9999)
    |> Json.encode
    |> Json.toString 0
    |> (==) "{\"type\":[1,[2,9999]]}"
    --> True


"{\"type\": [1, [2, \"tada\"] ]}"
    |> Json.decodeString
    |> Gen.set [Gen.String "type", Gen.Int 11, Gen.Int 11] (Gen.Int 9999)
    |> Json.encode
    |> Json.toString 0
    |> (==) "{\"type\":[1,[2,\"tada\"]]}"
    --> True

Transformations

toBool : Value -> Bool

Same as in JavaScript, tries to make a bool from every type

toBool Null --> False


toBool (Bool True) --> True


toBool (Bool False) --> False


toBool (Int 0) --> False


toBool (Int -1) --> True


toBool (Float 0.0) --> False


toBool (Float 3.141592) --> True


toBool (String "") --> False


toBool (String "misc") --> True


toBool (List []) --> True
toInt : Value -> Maybe Int

Convert a generic toy to Int, if possible

toInt Null --> Nothing


toInt (Bool True) --> Just 1


toInt (Bool False) --> Just 0


toInt (Int 0) --> Just 0


toInt (Int -1) --> Just -1


toInt (Float 0.0) --> Just 0


toInt (Float 3.141592) --> Just 3


toInt (String "") --> Nothing


toInt (String "33") --> Just 33


toInt (String "33.33") --> Just 33
toFloat : Value -> Maybe Float

Convert a generic type to Float, if possible

import Generic as Gen


Gen.toFloat Null --> Nothing


Gen.toFloat (Bool True) --> Just 1.0


Gen.toFloat (Bool False) --> Just 0.0


Gen.toFloat (Int 2) --> Just 2.0


Gen.toFloat (Int -1) --> Just -1.0


Gen.toFloat (Float 0.0) --> Just 0.0


Gen.toFloat (Float 3.141592) --> Just 3.141592


Gen.toFloat (String "") --> Nothing


Gen.toFloat (String "33") --> Just 33


Gen.toFloat (String "33 m") --> Nothing


Gen.toFloat (String "33.33") --> Just 33.33
toString : Value -> Maybe String

Convert a generic type to a string representation. Actually this works for any value, except for Null:

toString Null --> Nothing


toString (Bool True) --> Just "true"


toString (Bool False) --> Just "false"


toString (Int 2) --> Just "2"


toString (Int -1) --> Just "-1"


toString (Float 0.0) --> Just "0"


toString (Float 3.141592) --> Just "3.141592"


toString (String "") --> Just ""


toString (String "33") --> Just "33"


toString (String "33 m") --> Just "33 m"


toString (String "33.33") --> Just "33.33"


toString (List [ String "33.33", Null ]) --> Just "[\"33.33\",null]"
toList : Value -> List Value

Tries to turn every type into a list

import Generic as Gen


List [ Null, Int 12 ] |> toList --> [Null, Int 12]


List [ Null, Int 12, Int 12]
    |> toSet
    |> Set
    |> toList --> [Int 12, Null]
toDict : List ( Value, Value ) -> Dict Value Value

Turns a list of tuples of generic values into a generic dictionary.

[ ( Int 12, String "foo" ), ( Null, List [ Float 12.0, Null ] ) ]
    |> toDict
toSet : Value -> EverySet Value

Turns everything into a set of type EverySet, if possible. Passing a Dict will result in a set of dict values.

toDate : Value -> Maybe Posix

Try to get a Date value in Posix Format.

toDateTime : Value -> Maybe Posix

Try to get a DateTime value in Posix Format.