{-# LANGUAGE StandaloneKindSignatures #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE AllowAmbiguousTypes #-} -- why? {-# LANGUAGE GADTs #-} {-# LANGUAGE InstanceSigs #-} module Lib where import Data.Kind (Type) type GetRequest :: Type -> Type -- I know we can use associated types but I found this easier to follow type family GetRequest route type GetContext :: Type -> Type type family GetContext route type GetResponse :: Type -> Type type family GetResponse route class Route route where -- how we know which route to use requestKey :: route -> String -- parse the route into object, should be an either -- to signifiy this failed to deserialize for some reason requestParse :: route -> String -> GetRequest route -- transform request into response (will later return a new context as well) handle :: route -> GetRequest route -> GetResponse route -- handle :: GetContext route -> GetRequest route -> (GetContext route, GetResponse route) -- turn response object into string (will be json irl) responseSerialize :: route -> GetResponse route -> String data InitRoute = InitRoute data InitRequest = InitRequest type instance GetRequest InitRoute = InitRequest data InitResponse = InitResponse type instance GetResponse InitRoute = InitResponse instance Route InitRoute where requestKey _ = "init" requestParse _ _ = InitRequest handle _ InitRequest = InitResponse responseSerialize _ InitResponse = "init_ok" data ReadRoute = ReadRoute data ReadRequest = ReadRequest type instance GetRequest ReadRoute = ReadRequest data ReadResponse = ReadResponse type instance GetResponse ReadRoute = ReadResponse instance Route ReadRoute where requestKey _ = "read" requestParse _ _ = ReadRequest handle _ ReadRequest = ReadResponse responseSerialize _ ReadResponse = "read_ok" -- go through all the routes, see which ones match -- once we find a matching one return that type routeHandler :: [RouteHolder] -> (String, String) -> IO String routeHandler routes (reqType, reqPayload) = do -- irl add error handling let routeMatch = head $ filter (\route -> requestKey route == reqType) routes let parsedRequest = requestParse routeMatch reqPayload let response = handle routeMatch parsedRequest let serializedResponse = responseSerialize routeMatch response pure serializedResponse -- how to solve this?? {- Lists in haskell have to homogenous so we can't make this we can create a sum type to contain all the routes but do I want that? I tried creating a routeholder but that didn't work -} data RouteHolder = forall a. Route a => RouteHolder a instance Route RouteHolder where requestKey = requestKey requestParse = requestParse handle :: RouteHolder -> GetRequest RouteHolder -> GetResponse RouteHolder handle = handle responseSerialize = responseSerialize myRoutes :: [RouteHolder] myRoutes = [RouteHolder ReadRoute, RouteHolder InitRoute] fakeLines :: [String] fakeLines = ["init", "read", "something"] -- fake reading server :: Int -> IO () server lineNum = do let req = fakeLines !! lineNum resp <- routeHandler myRoutes (req, "") -- would be json not empty string irl print resp server (lineNum + 1) someFunc :: IO () someFunc = putStrLn "someFunc"