Haddocks
This commit is contained in:
parent
9e3fb00b44
commit
46a8394b4e
23
src/API.hs
23
src/API.hs
@ -4,6 +4,19 @@
|
|||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
{-|
|
||||||
|
Module : API
|
||||||
|
Description : The application API and handlers
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
Provides the API and handlers for the application.
|
||||||
|
|
||||||
|
Even if this is only one module, I'm using this same style in all of my projects. Each level of APIs provide their own `API` type and a `handler` who is responsible only for that specific subsection of an API.
|
||||||
|
-}
|
||||||
module API where
|
module API where
|
||||||
|
|
||||||
import Control.Monad.Reader (MonadReader, asks)
|
import Control.Monad.Reader (MonadReader, asks)
|
||||||
@ -25,11 +38,15 @@ import Data.Language
|
|||||||
import Solidabis.API (HasClientEnv, HasToken, bullshits,
|
import Solidabis.API (HasClientEnv, HasToken, bullshits,
|
||||||
getBullshits, message)
|
getBullshits, message)
|
||||||
|
|
||||||
|
-- | Data for the frontpage
|
||||||
|
--
|
||||||
|
-- Our "UI" only cares about the decrypted and non-decryptable sentences
|
||||||
data Index =
|
data Index =
|
||||||
Index { converted :: [Text]
|
Index { converted :: [Text]
|
||||||
, unconverted :: [Text]
|
, unconverted :: [Text]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
-- | Wrap a UI within an HTML page
|
||||||
page :: Monad m => HtmlT m () -> HtmlT m ()
|
page :: Monad m => HtmlT m () -> HtmlT m ()
|
||||||
page = doctypehtml_ . body_
|
page = doctypehtml_ . body_
|
||||||
|
|
||||||
@ -43,10 +60,16 @@ instance ToHtml Index where
|
|||||||
ul_ $ traverse_ (li_ . toHtml) unconverted
|
ul_ $ traverse_ (li_ . toHtml) unconverted
|
||||||
toHtmlRaw = toHtml
|
toHtmlRaw = toHtml
|
||||||
|
|
||||||
|
-- | Our API type
|
||||||
|
--
|
||||||
|
-- Consists only of the index route
|
||||||
newtype API route
|
newtype API route
|
||||||
= API { _index :: route :- Get '[HTML] Index }
|
= API { _index :: route :- Get '[HTML] Index }
|
||||||
deriving Generic
|
deriving Generic
|
||||||
|
|
||||||
|
-- | API handler
|
||||||
|
--
|
||||||
|
-- Compares the sentences given by the solidabis api against the model
|
||||||
handler
|
handler
|
||||||
:: (HasModel r, MonadReader r m, HasToken r, HasClientEnv r, MonadIO m)
|
:: (HasModel r, MonadReader r m, HasToken r, HasClientEnv r, MonadIO m)
|
||||||
=> API (AsServerT m)
|
=> API (AsServerT m)
|
||||||
|
@ -1,23 +1,43 @@
|
|||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-|
|
||||||
|
Module : Control.Lens
|
||||||
|
Description : Simplified functional lenses
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
A very small subset of the lens library reimplemented
|
||||||
|
|
||||||
|
See http://hackage.haskell.org/package/lens for proper docs
|
||||||
|
-}
|
||||||
module Control.Lens where
|
module Control.Lens where
|
||||||
|
|
||||||
import Control.Monad.Reader (MonadReader, asks)
|
import Control.Monad.Reader (MonadReader, asks)
|
||||||
import Data.Functor.Const (Const (..))
|
import Data.Functor.Const (Const (..))
|
||||||
import Data.Functor.Identity (Identity (..))
|
import Data.Functor.Identity (Identity (..))
|
||||||
|
|
||||||
|
-- | Full lens type
|
||||||
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
|
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
|
||||||
|
|
||||||
|
-- | Simplified lens type
|
||||||
type Lens' s b = Lens s s b b
|
type Lens' s b = Lens s s b b
|
||||||
|
|
||||||
|
-- | Build a lens out of a getter and a setter
|
||||||
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
|
lens :: (s -> a) -> (s -> b -> t) -> Lens s t a b
|
||||||
lens sa sbt afb s = sbt s <$> afb (sa s)
|
lens sa sbt afb s = sbt s <$> afb (sa s)
|
||||||
|
|
||||||
|
-- | Getting a value
|
||||||
type Getting r s a = (a -> Const r a) -> s -> Const r s
|
type Getting r s a = (a -> Const r a) -> s -> Const r s
|
||||||
|
|
||||||
|
-- | View a value
|
||||||
view :: MonadReader r m => Getting a r a -> m a
|
view :: MonadReader r m => Getting a r a -> m a
|
||||||
view l = asks (getConst . l Const)
|
view l = asks (getConst . l Const)
|
||||||
|
|
||||||
|
-- | Settering a value
|
||||||
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
|
type ASetter s t a b = (a -> Identity b) -> s -> Identity t
|
||||||
|
|
||||||
|
-- | Set a value
|
||||||
set :: ASetter s t a b -> b -> s -> t
|
set :: ASetter s t a b -> b -> s -> t
|
||||||
set l b = runIdentity . l (\_ -> Identity b)
|
set l b = runIdentity . l (\_ -> Identity b)
|
||||||
|
@ -1,5 +1,20 @@
|
|||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
{-# LANGUAGE RankNTypes #-}
|
{-# LANGUAGE RankNTypes #-}
|
||||||
|
{-|
|
||||||
|
Module : Control.Monad.App
|
||||||
|
Description : Our application monad
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
Provides the application monad, which is just a newtype over a ReaderT environment.
|
||||||
|
|
||||||
|
The environment contains the configuration as well as values determind at startup.
|
||||||
|
|
||||||
|
The environment can be thought of as dependency injection.
|
||||||
|
-}
|
||||||
module Control.Monad.App where
|
module Control.Monad.App where
|
||||||
|
|
||||||
import Control.Monad.Reader (MonadReader, ReaderT, runReaderT)
|
import Control.Monad.Reader (MonadReader, ReaderT, runReaderT)
|
||||||
@ -14,26 +29,33 @@ import Solidabis.API (HasClientEnv (..), HasToken (..), Token)
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
-- | Lens for accessing token
|
||||||
accessToken :: Lens' Config Token
|
accessToken :: Lens' Config Token
|
||||||
accessToken = lens _accessToken (\st x -> st{_accessToken=x})
|
accessToken = lens _accessToken (\st x -> st{_accessToken=x})
|
||||||
|
|
||||||
|
-- | Lens for accessing solidabis base url
|
||||||
solidabisBase :: Lens' Config BaseUrl
|
solidabisBase :: Lens' Config BaseUrl
|
||||||
solidabisBase = lens _solidabisBase (\st x -> st{_solidabisBase=x})
|
solidabisBase = lens _solidabisBase (\st x -> st{_solidabisBase=x})
|
||||||
|
|
||||||
|
-- | Lens for accessing the server port
|
||||||
port :: Lens' Config Port
|
port :: Lens' Config Port
|
||||||
port = lens _port (\st x -> st{_port = x})
|
port = lens _port (\st x -> st{_port = x})
|
||||||
|
|
||||||
|
-- | The environment
|
||||||
data App
|
data App
|
||||||
= App { _config :: Config
|
= App { _config :: Config
|
||||||
, _solidabisClient :: ClientEnv
|
, _solidabisClient :: ClientEnv
|
||||||
, _languageModel :: Model}
|
, _languageModel :: Model}
|
||||||
|
|
||||||
|
-- | Lens for accessing the config
|
||||||
config :: Lens' App Config
|
config :: Lens' App Config
|
||||||
config = lens _config (\st x -> st{_config=x})
|
config = lens _config (\st x -> st{_config=x})
|
||||||
|
|
||||||
|
-- | Lens for accessing the client environment
|
||||||
solidabisClient :: Lens' App ClientEnv
|
solidabisClient :: Lens' App ClientEnv
|
||||||
solidabisClient = lens _solidabisClient (\st x -> st{_solidabisClient=x})
|
solidabisClient = lens _solidabisClient (\st x -> st{_solidabisClient=x})
|
||||||
|
|
||||||
|
-- | Lens for accessing the language model
|
||||||
model :: Lens' App Model
|
model :: Lens' App Model
|
||||||
model = lens _languageModel (\st x -> st{_languageModel=x})
|
model = lens _languageModel (\st x -> st{_languageModel=x})
|
||||||
|
|
||||||
@ -53,8 +75,12 @@ instance HasModel App where
|
|||||||
getModel = view model
|
getModel = view model
|
||||||
setModel app tk = set model tk app
|
setModel app tk = set model tk app
|
||||||
|
|
||||||
|
-- | The application monad
|
||||||
|
--
|
||||||
|
-- This is just a 'ReaderT App IO'
|
||||||
newtype AppM a = AppM (ReaderT App IO a)
|
newtype AppM a = AppM (ReaderT App IO a)
|
||||||
deriving (Functor, Applicative, Monad, MonadReader App, MonadIO)
|
deriving (Functor, Applicative, Monad, MonadReader App, MonadIO)
|
||||||
|
|
||||||
|
-- | Run the application monad into IO
|
||||||
runAppM :: App -> AppM a -> IO a
|
runAppM :: App -> AppM a -> IO a
|
||||||
runAppM st (AppM f) = runReaderT f st
|
runAppM st (AppM f) = runReaderT f st
|
||||||
|
@ -1,7 +1,21 @@
|
|||||||
|
{-|
|
||||||
|
Module : Data.Caesar
|
||||||
|
Description : Utilities for doing caesar transforms
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
-}
|
||||||
module Data.Caesar where
|
module Data.Caesar where
|
||||||
|
|
||||||
|
-- | Type alias over char
|
||||||
type Caesar = Char
|
type Caesar = Char
|
||||||
|
|
||||||
|
-- | Translate to the next character on the left
|
||||||
|
--
|
||||||
|
-- Has special handling for some symbols
|
||||||
next :: Char -> Char
|
next :: Char -> Char
|
||||||
next c =
|
next c =
|
||||||
case c of
|
case c of
|
||||||
@ -13,5 +27,6 @@ next c =
|
|||||||
'a' -> 'ö'
|
'a' -> 'ö'
|
||||||
x -> pred x
|
x -> pred x
|
||||||
|
|
||||||
|
-- | Translate a character n times
|
||||||
caesar :: Int -> Caesar -> Caesar
|
caesar :: Int -> Caesar -> Caesar
|
||||||
caesar n x = foldr ($) x (replicate n next)
|
caesar n x = foldr ($) x (replicate n next)
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
{-# LANGUAGE DeriveGeneric #-}
|
{-# LANGUAGE DeriveGeneric #-}
|
||||||
|
{-|
|
||||||
|
Module : Config
|
||||||
|
Description : Config types
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
The config type with a helper function for reading the config from disk
|
||||||
|
-}
|
||||||
module Data.Config where
|
module Data.Config where
|
||||||
|
|
||||||
import Server (Port)
|
import Server (Port)
|
||||||
@ -10,6 +21,9 @@ import Data.Yaml.Config
|
|||||||
import GHC.Generics (Generic)
|
import GHC.Generics (Generic)
|
||||||
import Servant.Client (BaseUrl)
|
import Servant.Client (BaseUrl)
|
||||||
|
|
||||||
|
-- | Config type
|
||||||
|
--
|
||||||
|
-- These are all values that should be known statically beforehand
|
||||||
data Config
|
data Config
|
||||||
= Config { _accessToken :: Token
|
= Config { _accessToken :: Token
|
||||||
, _solidabisBase :: BaseUrl
|
, _solidabisBase :: BaseUrl
|
||||||
@ -19,5 +33,6 @@ data Config
|
|||||||
|
|
||||||
instance FromJSON Config
|
instance FromJSON Config
|
||||||
|
|
||||||
|
-- | Read the configuration yaml from file
|
||||||
readConfigFromFile :: MonadIO m => FilePath -> m Config
|
readConfigFromFile :: MonadIO m => FilePath -> m Config
|
||||||
readConfigFromFile path = liftIO $ loadYamlSettings [path] [] ignoreEnv
|
readConfigFromFile path = liftIO $ loadYamlSettings [path] [] ignoreEnv
|
||||||
|
@ -1,4 +1,17 @@
|
|||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
{-|
|
||||||
|
Module : Data.Language
|
||||||
|
Description : The language model
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
An n-gram model over a language. Should be trained with regular text.
|
||||||
|
|
||||||
|
The idea behind this module is to compare a sentence n-grams against the model. Higher the results, higher the probability of it being the same language as the model.
|
||||||
|
-}
|
||||||
module Data.Language where
|
module Data.Language where
|
||||||
|
|
||||||
import Data.Foldable (fold)
|
import Data.Foldable (fold)
|
||||||
@ -10,10 +23,12 @@ import Data.Text (Text)
|
|||||||
|
|
||||||
import Data.NGram
|
import Data.NGram
|
||||||
|
|
||||||
|
-- | Model represents the language
|
||||||
data Model
|
data Model
|
||||||
= Model { parts :: Map Text (Sum Int)
|
= Model { parts :: Map Text (Sum Int)
|
||||||
, total :: Sum Int }
|
, total :: Sum Int }
|
||||||
|
|
||||||
|
-- | Has* style pattern for accessing the language model
|
||||||
class HasModel a where
|
class HasModel a where
|
||||||
getModel :: a -> Model
|
getModel :: a -> Model
|
||||||
setModel :: a -> Model -> a
|
setModel :: a -> Model -> a
|
||||||
@ -22,15 +37,20 @@ instance HasModel Model where
|
|||||||
getModel = id
|
getModel = id
|
||||||
setModel = const
|
setModel = const
|
||||||
|
|
||||||
|
-- | The default n-gram size
|
||||||
ngramSize :: Int
|
ngramSize :: Int
|
||||||
ngramSize = 3
|
ngramSize = 3
|
||||||
|
|
||||||
|
-- | Build a language model out of a corpus content
|
||||||
buildModel :: Text -> Model
|
buildModel :: Text -> Model
|
||||||
buildModel str =
|
buildModel str =
|
||||||
let parts = ngram ngramSize str
|
let parts = ngram ngramSize str
|
||||||
total = fold parts
|
total = fold parts
|
||||||
in Model{..}
|
in Model{..}
|
||||||
|
|
||||||
|
-- | Calculate the 'goodness' of a sentence
|
||||||
|
--
|
||||||
|
-- Higher numbers means higher probability of being part of the same language as the model
|
||||||
goodness :: Model -> Text -> Double
|
goodness :: Model -> Text -> Double
|
||||||
goodness Model{..} str =
|
goodness Model{..} str =
|
||||||
let comparison = M.keys $ ngram ngramSize str
|
let comparison = M.keys $ ngram ngramSize str
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-|
|
||||||
|
Module : Data.NGram
|
||||||
|
Description : N-gram utilities
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
Utilities for building n-gram models
|
||||||
|
-}
|
||||||
module Data.NGram where
|
module Data.NGram where
|
||||||
|
|
||||||
import Data.List (unfoldr)
|
import Data.List (unfoldr)
|
||||||
@ -8,6 +19,7 @@ import Data.Monoid (Sum (..))
|
|||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
|
|
||||||
|
-- | Build a n-gram frequency map
|
||||||
ngram :: Int -> Text -> Map Text (Sum Int)
|
ngram :: Int -> Text -> Map Text (Sum Int)
|
||||||
ngram n = M.unionsWith (<>) . unfoldr go
|
ngram n = M.unionsWith (<>) . unfoldr go
|
||||||
where
|
where
|
||||||
|
17
src/Main.hs
17
src/Main.hs
@ -3,6 +3,18 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
{-|
|
||||||
|
Module : Main
|
||||||
|
Description : The main module
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
|
||||||
|
The main access point for the koodihaaste
|
||||||
|
-}
|
||||||
module Main where
|
module Main where
|
||||||
|
|
||||||
import Control.Monad.App
|
import Control.Monad.App
|
||||||
@ -14,11 +26,16 @@ import Options.Generic
|
|||||||
import Servant.Client
|
import Servant.Client
|
||||||
import Server
|
import Server
|
||||||
|
|
||||||
|
-- | The command line endpoint
|
||||||
|
--
|
||||||
|
-- Parses only the path to the config file
|
||||||
|
-- see config.yaml.sample for the format
|
||||||
newtype Cmd = Cmd (FilePath <?> "Config path")
|
newtype Cmd = Cmd (FilePath <?> "Config path")
|
||||||
deriving Generic
|
deriving Generic
|
||||||
|
|
||||||
instance ParseRecord Cmd
|
instance ParseRecord Cmd
|
||||||
|
|
||||||
|
-- | The main function
|
||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = do
|
main = do
|
||||||
Cmd (Helpful configPath) <- getRecord "koodihaaste"
|
Cmd (Helpful configPath) <- getRecord "koodihaaste"
|
||||||
|
@ -1,4 +1,15 @@
|
|||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
||||||
|
{-|
|
||||||
|
Module : Server
|
||||||
|
Description : Run the http server
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
|
||||||
|
-}
|
||||||
module Server where
|
module Server where
|
||||||
|
|
||||||
import Control.Monad.Reader (MonadReader, ask, asks, runReaderT)
|
import Control.Monad.Reader (MonadReader, ask, asks, runReaderT)
|
||||||
@ -12,8 +23,14 @@ import API (handler)
|
|||||||
import Data.Language (HasModel)
|
import Data.Language (HasModel)
|
||||||
import Solidabis.API (HasClientEnv, HasToken)
|
import Solidabis.API (HasClientEnv, HasToken)
|
||||||
|
|
||||||
|
-- | The port to run on
|
||||||
|
--
|
||||||
|
-- Should be provided within the environment
|
||||||
newtype Port = Port Int deriving (Show, FromJSON)
|
newtype Port = Port Int deriving (Show, FromJSON)
|
||||||
|
|
||||||
|
-- | Has* pattern
|
||||||
|
--
|
||||||
|
-- Locate the port within the larger environment structure
|
||||||
class HasPort a where
|
class HasPort a where
|
||||||
getPort :: a -> Port
|
getPort :: a -> Port
|
||||||
setPort :: a -> Port -> a
|
setPort :: a -> Port -> a
|
||||||
@ -22,9 +39,11 @@ instance HasPort Port where
|
|||||||
getPort = id
|
getPort = id
|
||||||
setPort = const
|
setPort = const
|
||||||
|
|
||||||
|
-- | Convert the servant handler into wai application
|
||||||
app :: (HasModel r, HasClientEnv r, HasToken r) => r -> Application
|
app :: (HasModel r, HasClientEnv r, HasToken r) => r -> Application
|
||||||
app env = genericServeT (`runReaderT` env) API.handler
|
app env = genericServeT (`runReaderT` env) API.handler
|
||||||
|
|
||||||
|
-- | Run the server
|
||||||
server
|
server
|
||||||
:: (HasModel r, HasClientEnv r, HasToken r, HasPort r, MonadReader r m, MonadIO m)
|
:: (HasModel r, HasClientEnv r, HasToken r, HasPort r, MonadReader r m, MonadIO m)
|
||||||
=> m ()
|
=> m ()
|
||||||
|
@ -4,6 +4,17 @@
|
|||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE TypeFamilies #-}
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
{-# LANGUAGE TypeOperators #-}
|
{-# LANGUAGE TypeOperators #-}
|
||||||
|
{-|
|
||||||
|
Module : Solidabis.API
|
||||||
|
Description : The client API for solidabis API
|
||||||
|
Copyright : (c) Mats Rauhala, 2019
|
||||||
|
License : BSD3
|
||||||
|
Maintainer : mats.rauhala@iki.fi
|
||||||
|
Stability : experimental
|
||||||
|
Portability : POSIX
|
||||||
|
|
||||||
|
Provides the client API for the solidabis API. Implemented through servant generics.
|
||||||
|
-}
|
||||||
module Solidabis.API
|
module Solidabis.API
|
||||||
( getBullshits
|
( getBullshits
|
||||||
, Bullshit(..)
|
, Bullshit(..)
|
||||||
@ -28,9 +39,11 @@ import Servant.Client.Core.Request (Request)
|
|||||||
import qualified Servant.Client.Core.Request as Req
|
import qualified Servant.Client.Core.Request as Req
|
||||||
import Servant.Client.Generic
|
import Servant.Client.Generic
|
||||||
|
|
||||||
|
-- | JSON representation of the message layer
|
||||||
newtype Message = Message { message :: Text }
|
newtype Message = Message { message :: Text }
|
||||||
deriving Generic
|
deriving Generic
|
||||||
|
|
||||||
|
-- | JSON representation of the bullshit layer
|
||||||
newtype Bullshit
|
newtype Bullshit
|
||||||
= Bullshit { bullshits :: [ Message ] }
|
= Bullshit { bullshits :: [ Message ] }
|
||||||
deriving Generic
|
deriving Generic
|
||||||
@ -42,6 +55,7 @@ newtype API route
|
|||||||
= API { _bullshit :: route :- AuthProtect "jwt" :> "bullshit" :> Get '[JSON] Bullshit }
|
= API { _bullshit :: route :- AuthProtect "jwt" :> "bullshit" :> Get '[JSON] Bullshit }
|
||||||
deriving (Generic)
|
deriving (Generic)
|
||||||
|
|
||||||
|
-- | Has* style pattern for accessing the client environment
|
||||||
class HasClientEnv a where
|
class HasClientEnv a where
|
||||||
getClientEnv :: a -> ClientEnv
|
getClientEnv :: a -> ClientEnv
|
||||||
setClientEnv :: a -> ClientEnv -> a
|
setClientEnv :: a -> ClientEnv -> a
|
||||||
@ -54,9 +68,11 @@ routes :: (MonadReader r m, MonadIO m, HasClientEnv r) => API (AsClientT m)
|
|||||||
routes = genericClientHoist
|
routes = genericClientHoist
|
||||||
(\x -> asks getClientEnv >>= \env -> liftIO (runClientM x env >>= either throwIO return))
|
(\x -> asks getClientEnv >>= \env -> liftIO (runClientM x env >>= either throwIO return))
|
||||||
|
|
||||||
|
-- | Newtype wrapper over the jwt token
|
||||||
newtype Token = Token String
|
newtype Token = Token String
|
||||||
deriving (Semigroup, Monoid, ToHttpApiData, IsString, Show, FromJSON)
|
deriving (Semigroup, Monoid, ToHttpApiData, IsString, Show, FromJSON)
|
||||||
|
|
||||||
|
-- | Has* style pattern for accessing the authentication token
|
||||||
class HasToken a where
|
class HasToken a where
|
||||||
getToken :: a -> Token
|
getToken :: a -> Token
|
||||||
setToken :: a -> Token -> a
|
setToken :: a -> Token -> a
|
||||||
@ -70,6 +86,7 @@ type instance AuthClientData (AuthProtect "jwt") = Token
|
|||||||
authReq :: Token -> Request -> Request
|
authReq :: Token -> Request -> Request
|
||||||
authReq token = Req.addHeader "Authorization" ("Bearer " <> token)
|
authReq token = Req.addHeader "Authorization" ("Bearer " <> token)
|
||||||
|
|
||||||
|
-- | Return the encoded sentences from the solidabis API
|
||||||
getBullshits
|
getBullshits
|
||||||
:: (HasToken r, MonadReader r m, MonadIO m, HasClientEnv r)
|
:: (HasToken r, MonadReader r m, MonadIO m, HasClientEnv r)
|
||||||
=> m Bullshit
|
=> m Bullshit
|
||||||
|
Loading…
Reference in New Issue
Block a user