roc/examples/Community.roc
2023-08-16 19:17:47 +02:00

150 lines
4.2 KiB
Text

interface Community
exposes [
Community,
empty,
addPerson,
addFriend,
Person,
walkFriendNames,
]
imports []
## Datatype representing a community for demonstration purposes in inspect-gui.roc and inspect-logging.roc
Community := {
people : List Person,
friends : List (Set Nat),
}
implements [
Inspect {
toInspector: inspectCommunity,
},
]
Person := {
firstName : Str,
lastName : Str,
age : U8,
hasBeard : Bool,
favoriteColor : Color,
}
implements [
Inspect {
toInspector: inspectPerson,
},
]
Color : [
Red,
Green,
Blue,
RGB (U8, U8, U8),
]
empty = @Community { people: [], friends: [] }
addPerson = \@Community { people, friends }, person ->
@Community {
people: List.append people (@Person person),
friends: List.append friends (Set.empty {}),
}
addFriend = \@Community { people, friends }, from, to ->
when (List.get friends from, List.get friends to) is
(Ok fromSet, Ok toSet) ->
@Community {
people,
friends: friends
|> List.set from (Set.insert fromSet to)
|> List.set to (Set.insert toSet from),
}
_ ->
@Community { people, friends }
walkFriendNames : Community, state, (state, Str, Set Str -> state) -> state
walkFriendNames = \@Community { people, friends }, s0, nextFn ->
(out, _) =
(s1, id), friendSet <- List.walk friends (s0, 0)
(@Person person) =
when List.get people id is
Ok v -> v
Err _ -> crash "Unknown Person"
personName =
person.firstName
|> Str.concat " "
|> Str.concat person.lastName
friendNames =
friendsSet, friendId <- Set.walk friendSet (Set.empty {})
(@Person friend) =
when List.get people friendId is
Ok v -> v
Err _ -> crash "Unknown Person"
friendName =
friend.firstName
|> Str.concat " "
|> Str.concat friend.lastName
Set.insert friendsSet friendName
(nextFn s1 personName friendNames, id + 1)
out
# The functions below will be auto-generated in the future
inspectCommunity : Community -> Inspector f where f implements InspectFormatter
inspectCommunity = \@Community { people, friends } ->
f0 <- Inspect.custom
[
{ key: "people", value: Inspect.list people List.walk Inspect.toInspector },
{
key: "friends",
value: Inspect.list
friends
List.walk
(\s -> Inspect.set
s
Set.walk
(\num -> num |> Num.toU64 |> Inspect.u64)
),
# value: Inspect.dict
# (@Community { people, friends })
# walkFriendNames
# Inspect.str
# (\s -> Inspect.set s Set.walk Inspect.str),
},
]
|> Inspect.record
|> Inspect.apply f0
inspectPerson : Person -> Inspector f where f implements InspectFormatter
inspectPerson = \@Person { firstName, lastName, age, hasBeard, favoriteColor } ->
# In practice, this would never be done manually due to autoderive.
# Instead you would just write:
# Inspect.inspect innerRecord
# This is what the auto-derive would generate.
f0 <- Inspect.custom
favoriteColorTag =
when favoriteColor is
Red ->
Inspect.tag "Red" []
Green ->
Inspect.tag "Green" []
Blue ->
Inspect.tag "Blue" []
RGB (r, g, b) ->
Inspect.tag "RGB" [Inspect.tuple [Inspect.u8 r, Inspect.u8 g, Inspect.u8 b]]
[
{ key: "firstName", value: Inspect.str firstName },
{ key: "lastName", value: Inspect.str lastName },
{ key: "age", value: Inspect.u8 age },
{ key: "hasBeard", value: Inspect.bool hasBeard },
{ key: "favoriteColor", value: favoriteColorTag },
]
|> Inspect.record
|> Inspect.apply f0