{-# LANGUAGE OverloadedStrings #-}

-- |
-- Module      :  Mcmc.Item
-- Description :  Links of Markov chains
-- Copyright   :  (c) Dominik Schrempf 2020
-- License     :  GPL-3.0-or-later
--
-- Maintainer  :  dominik.schrempf@gmail.com
-- Stability   :  unstable
-- Portability :  portable
--
-- Creation date: Wed May 20 09:10:27 2020.
module Mcmc.Item
  ( Item (..),
  )
where

import Data.Aeson
import Data.Aeson.Types
import Numeric.Log

-- | An 'Item', or link of the Markov chain. For reasons of computational
-- efficiency, each state is associated with the corresponding prior and
-- likelihood.
data Item a = Item
  { -- | The current state in the state space @a@.
    Item a -> a
state :: a,
    -- | The current prior.
    Item a -> Log Double
prior :: Log Double,
    -- | The current likelihood.
    Item a -> Log Double
likelihood :: Log Double
  }
  deriving (Item a -> Item a -> Bool
(Item a -> Item a -> Bool)
-> (Item a -> Item a -> Bool) -> Eq (Item a)
forall a. Eq a => Item a -> Item a -> Bool
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: Item a -> Item a -> Bool
$c/= :: forall a. Eq a => Item a -> Item a -> Bool
== :: Item a -> Item a -> Bool
$c== :: forall a. Eq a => Item a -> Item a -> Bool
Eq, Eq (Item a)
Eq (Item a)
-> (Item a -> Item a -> Ordering)
-> (Item a -> Item a -> Bool)
-> (Item a -> Item a -> Bool)
-> (Item a -> Item a -> Bool)
-> (Item a -> Item a -> Bool)
-> (Item a -> Item a -> Item a)
-> (Item a -> Item a -> Item a)
-> Ord (Item a)
Item a -> Item a -> Bool
Item a -> Item a -> Ordering
Item a -> Item a -> Item a
forall a.
Eq a
-> (a -> a -> Ordering)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> Bool)
-> (a -> a -> a)
-> (a -> a -> a)
-> Ord a
forall a. Ord a => Eq (Item a)
forall a. Ord a => Item a -> Item a -> Bool
forall a. Ord a => Item a -> Item a -> Ordering
forall a. Ord a => Item a -> Item a -> Item a
min :: Item a -> Item a -> Item a
$cmin :: forall a. Ord a => Item a -> Item a -> Item a
max :: Item a -> Item a -> Item a
$cmax :: forall a. Ord a => Item a -> Item a -> Item a
>= :: Item a -> Item a -> Bool
$c>= :: forall a. Ord a => Item a -> Item a -> Bool
> :: Item a -> Item a -> Bool
$c> :: forall a. Ord a => Item a -> Item a -> Bool
<= :: Item a -> Item a -> Bool
$c<= :: forall a. Ord a => Item a -> Item a -> Bool
< :: Item a -> Item a -> Bool
$c< :: forall a. Ord a => Item a -> Item a -> Bool
compare :: Item a -> Item a -> Ordering
$ccompare :: forall a. Ord a => Item a -> Item a -> Ordering
$cp1Ord :: forall a. Ord a => Eq (Item a)
Ord, Int -> Item a -> ShowS
[Item a] -> ShowS
Item a -> String
(Int -> Item a -> ShowS)
-> (Item a -> String) -> ([Item a] -> ShowS) -> Show (Item a)
forall a. Show a => Int -> Item a -> ShowS
forall a. Show a => [Item a] -> ShowS
forall a. Show a => Item a -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Item a] -> ShowS
$cshowList :: forall a. Show a => [Item a] -> ShowS
show :: Item a -> String
$cshow :: forall a. Show a => Item a -> String
showsPrec :: Int -> Item a -> ShowS
$cshowsPrec :: forall a. Show a => Int -> Item a -> ShowS
Show, ReadPrec [Item a]
ReadPrec (Item a)
Int -> ReadS (Item a)
ReadS [Item a]
(Int -> ReadS (Item a))
-> ReadS [Item a]
-> ReadPrec (Item a)
-> ReadPrec [Item a]
-> Read (Item a)
forall a. Read a => ReadPrec [Item a]
forall a. Read a => ReadPrec (Item a)
forall a. Read a => Int -> ReadS (Item a)
forall a. Read a => ReadS [Item a]
forall a.
(Int -> ReadS a)
-> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
readListPrec :: ReadPrec [Item a]
$creadListPrec :: forall a. Read a => ReadPrec [Item a]
readPrec :: ReadPrec (Item a)
$creadPrec :: forall a. Read a => ReadPrec (Item a)
readList :: ReadS [Item a]
$creadList :: forall a. Read a => ReadS [Item a]
readsPrec :: Int -> ReadS (Item a)
$creadsPrec :: forall a. Read a => Int -> ReadS (Item a)
Read)

instance ToJSON a => ToJSON (Item a) where
  toJSON :: Item a -> Value
toJSON (Item a
x (Exp Double
p) (Exp Double
l)) = [Pair] -> Value
object [Text
"s" Text -> a -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= a
x, Text
"p" Text -> Double -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
p, Text
"l" Text -> Double -> Pair
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
l]
  toEncoding :: Item a -> Encoding
toEncoding (Item a
x (Exp Double
p) (Exp Double
l)) = Series -> Encoding
pairs (Text
"s" Text -> a -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= a
x Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<> Text
"p" Text -> Double -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
p Series -> Series -> Series
forall a. Semigroup a => a -> a -> a
<> Text
"l" Text -> Double -> Series
forall kv v. (KeyValue kv, ToJSON v) => Text -> v -> kv
.= Double
l)

item :: FromJSON a => Object -> Parser (Item a)
item :: Object -> Parser (Item a)
item Object
v = do
  a
s <- Object
v Object -> Text -> Parser a
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"s"
  Double
p <- Object
v Object -> Text -> Parser Double
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"p"
  Double
l <- Object
v Object -> Text -> Parser Double
forall a. FromJSON a => Object -> Text -> Parser a
.: Text
"l"
  Item a -> Parser (Item a)
forall (m :: * -> *) a. Monad m => a -> m a
return (Item a -> Parser (Item a)) -> Item a -> Parser (Item a)
forall a b. (a -> b) -> a -> b
$ a -> Log Double -> Log Double -> Item a
forall a. a -> Log Double -> Log Double -> Item a
Item a
s (Double -> Log Double
forall a. a -> Log a
Exp Double
p) (Double -> Log Double
forall a. a -> Log a
Exp Double
l)

instance FromJSON a => FromJSON (Item a) where
  parseJSON :: Value -> Parser (Item a)
parseJSON = String -> (Object -> Parser (Item a)) -> Value -> Parser (Item a)
forall a. String -> (Object -> Parser a) -> Value -> Parser a
withObject String
"Item" Object -> Parser (Item a)
forall a. FromJSON a => Object -> Parser (Item a)
item