Code Snippet

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import Html exposing (br, div, text)


type alias Stringable a =
    { stringable : a -> String }



-- Basics.toString going to Debug.toString in Elm 0.19 right?


toString : Stringable a -> a -> String
toString { stringable } x =
    stringable x



-- Primitive Types (The basic types built-into Elm: Int, Char, Float, ...):


int : Stringable Int
int =
    {- Obviously this will be changed with Int.toString in 0.19 -}
    { stringable = \x -> Basics.toString x }


char : Stringable Char
char =
    {- Obviously this will be changed with Char.toString in 0.19 -}
    { stringable = \x -> Basics.toString x }


float : Stringable Float
float =
    {- Obviously this will be changed with Float.toString in 0.19 -}
    { stringable = \x -> Basics.toString x }



-- Composite Types: (List, Array, ... but also custom made like Tree)


list : Stringable a -> Stringable (List a)
list nestedStringable =
    { stringable =
        \xs ->
            let
                str =
                    xs
                        |> List.map (toString nestedStringable)
                        |> List.reverse
                        |> List.foldl (\a b -> a ++ ", " ++ b) ""
                        |> String.dropRight 2
            in
            "[ " ++ str ++ " ]"
    }



-- Custom types built with primitive (core Elm) types


type alias FooBar =
    { foo : Int
    , bar : Char
    }


type BazQux
    = BazQux Int


foobar : Stringable FooBar
foobar =
    { stringable =
        \{ foo, bar } ->
            "FooBar { "
                ++ "foo: "
                ++ toString int foo
                ++ ", bar: "
                ++ toString char bar
                ++ " }"
    }


bazqux : Stringable BazQux
bazqux =
    { stringable = \(BazQux x) -> "BazQux " ++ toString int x }



-- Usage:


example00 =
    let
        str =
            [ 42.0, 43.0, 44.0 ]
                |> toString (list float)
    in
    "-- List of Floats: " ++ str


example01 =
    let
        str =
            toString foobar (FooBar 42 'c')
    in
    "-- Custom (product) type: " ++ str


example02 =
    let
        str =
            toString bazqux (BazQux 42)
    in
    "-- Custom (sum) type: " ++ str


main =
    div []
        [ text example00
        , br [] []
        , text example01
        , br [] []
        , text example02
        , br [] []
        ]

Code output:

-- List of Floats: [ 42, 43, 44 ]
-- Custom (product) type: FooBar { foo: 42, bar: 'c' }
-- Custom (sum) type: BazQux 42

References: