Created
September 18, 2024 22:21
-
-
Save solomon-b/844ab8e6f5364416b21b9a8b6fc3d00e to your computer and use it in GitHub Desktop.
Old example for using Singletones to build a typesafe API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| {-# LANGUAGE DeriveAnyClass #-} | |
| {-# LANGUAGE UndecidableInstances #-} | |
| {-# LANGUAGE DefaultSignatures #-} | |
| module API where | |
| import qualified Data.Text as T | |
| import qualified Data.Aeson as J | |
| import Control.Monad.IO.Class | |
| import qualified Data.ByteString as B | |
| import qualified Data.ByteString.Lazy as BL | |
| import GHC.Generics | |
| import Data.Foldable | |
| data EventType = Name | Topic | Other | |
| data EventTypeTag et where | |
| NameType :: EventTypeTag Name | |
| TopicType :: EventTypeTag Topic | |
| OtherType :: T.Text -> EventTypeTag Other | |
| instance Show (EventTypeTag Name) where | |
| show NameType = "M.name" | |
| instance Show (EventTypeTag Topic) where | |
| show TopicType = "M.topic" | |
| instance Show (EventTypeTag Other) where | |
| show (OtherType key) = T.unpack key | |
| newtype MRName = MRName T.Text | |
| instance J.FromJSON MRName where | |
| parseJSON = J.withObject "MRName" $ \o -> do | |
| name <- o J..: "name" | |
| pure $ MRName name | |
| data StateContent et where | |
| ScName :: MRName -> StateContent Name | |
| ScTopic :: T.Text -> StateContent Topic | |
| ScOther :: J.Value -> StateContent Other | |
| instance J.FromJSON (StateContent Name) where | |
| parseJSON v = ScName <$> J.parseJSON v | |
| --parseJSON = J.withObject "RoomName" $ \o -> do | |
| -- name <- o J..: "name" | |
| -- pure $ ScName name | |
| instance J.FromJSON (StateContent Topic) where | |
| parseJSON = J.withObject "RoomTopic" $ \o -> do | |
| name <- o J..: "topic" | |
| pure $ ScTopic name | |
| instance J.FromJSON (StateContent Other) where | |
| parseJSON = J.withObject "Other" $ \o -> do | |
| name <- o J..: "other" | |
| pure $ ScOther name | |
| data StateEvent et = StateEvent | |
| { content :: (StateContent et) | |
| , id :: Int -- ... | |
| } deriving stock (Generic) | |
| deriving anyclass instance (J.FromJSON (StateContent et)) => J.FromJSON (StateEvent et) | |
| -- Constraint Synonyms | |
| class (J.FromJSON (StateEvent et), Show (EventTypeTag et)) => FetchableEvent et | |
| instance (J.FromJSON (StateEvent et), Show (EventTypeTag et)) => FetchableEvent et | |
| fetchStateEvent :: (J.FromJSON (StateEvent et), Show (EventTypeTag et)) => | |
| ID -> EventTypeTag et -> IO (Either String (StateEvent et)) | |
| fetchStateEvent id et = | |
| let url = "/_matrix/client/v3/rooms/" <> "123" <> "/state" <> show et <> "/" <> "xyz" | |
| in fmap J.eitherDecode $ restCall url | |
| type ID = Int | |
| restCall :: String -> IO BL.ByteString | |
| restCall = error | |
| --fetchStateEvent :: ID -> EventTypeTag et -> IO (StateEvent et) | |
| --fetchStateEvent id tag = fmap _ $ restCall $ show $ Some tag | |
| data Some f = forall x. Some (f x) | |
| -- class RenderKey key where | |
| instance Show (Some EventTypeTag) where | |
| show (Some NameType) = "M.Name" | |
| show (Some TopicType) = "M.Topic" | |
| show (Some (OtherType key)) = T.unpack key | |
| instance J.FromJSON (Some StateEvent) where | |
| parseJSON val = asum [ Some <$> J.parseJSON @(StateEvent Name) val | |
| , Some <$> J.parseJSON @(StateEvent Topic) val | |
| , Some <$> J.parseJSON @(StateEvent Other) val | |
| ] | |
| fetchEvents :: IO (Either String [Some StateEvent]) | |
| fetchEvents = fmap J.eitherDecode $ restCall $ "/_matrix/client/v3/rooms/" <> "xyz" <> "/state" | |
| --useEvents :: Some StateEvent -> () | |
| --useEvents (Some (StateEvent (ScName txt) n)) = _wc | |
| --useEvents (Some (StateEvent (ScTopic txt) n)) = _wd | |
| --useEvents (Some (StateEvent (ScOther va) n)) = _we | |
| -- | |
| useEvents' :: StateEvent Name -> () | |
| useEvents' (StateEvent (ScName (MRName txt)) n) = () | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment