1{-# LANGUAGE DeriveGeneric, OverloadedStrings #-}
2--this example shows how to implement a non-generics-defined Tupleable instance which is required in scenarios where Haskell-side types are not supported server-side or where one wishes to represent a nested relation
3import ProjectM36.Client
5import ProjectM36.Tupleable
6import ProjectM36.Relation
8import ProjectM36.Attribute as A
9import qualified Data.Set as S
10import qualified Data.Map as M
11import Data.Text (Text)
15--in this contrived example, we wish to represent one relation with a nested relation of comments
18 comments :: S.Set Comment
21data Comment = Comment {
24 } deriving (Eq, Show, Generic, Ord)
26instance Tupleable Comment
28instance Tupleable Blog where
30 mkRelationTupleFromMap (M.fromList [("title", TextAtom (title blogentry)),
31 ("comments", RelationAtom relFromComments)])
33 commentTuples = map toTuple (S.toList (comments blogentry))
34 relFromComments = case mkRelationFromTuples (toAttributes (Proxy :: Proxy Comment)) commentTuples of
35 Left err -> error (show err)
39 titleAtom <- atomForAttributeName "title" tupIn
40 commentsAtom <- atomForAttributeName "comments" tupIn
41 commentsRel <- relationForAtom commentsAtom
42 comments' <- mapM fromTuple (tuplesList commentsRel)
44 title = atomToText titleAtom,
45 comments = S.fromList comments'}
47 toAttributes _ = A.attributesFromList [Attribute "title" TextAtomType,
48 Attribute "comments" $ RelationAtomType (toAttributes (Proxy :: Proxy Comment))]
52 let exampleBlog = Blog { title = "Cat Pics",
53 comments = S.fromList [Comment {authorName = "Steve",
55 Comment {authorName = "Bob",
58 print (toTuple exampleBlog)
59 print (fromTuple (toTuple exampleBlog) :: Either RelationalError Blog)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list