\begin{code}
{-# OPTIONS --cubical --safe --postfix-projections #-}

open import Algebra
open import HLevels
open import Level

module Control.Monad.Weighted.Expect {ā„“} {š‘… : Type ā„“} (rng : Semiring š‘…) (cIsSet : isSet š‘…) where

open Semiring rng renaming (+-comm to +-com)

open import Level
open import Path
open import Path.Reasoning
open import Data.Sigma

open import Control.Monad.Weighted.Definition rng
open import Control.Monad.Weighted.Eliminators rng
open import Control.Monad.Weighted.Functor rng
open import Control.Monad.Weighted.Functor.TypeDef
open import Function
open import Data.Lift
open import HITs.PropositionalTruncation
open import Data.Sum

-- member-at : {A : Type a} ā†’ š‘… ā†’ A ā†’  Weighted A ā†’ Type (a ā„“āŠ” ā„“)
-- member-at {a = a} {A = A} w x xs = fst (āŸ¦ alg x āŸ§ xs w)
--   where
--   alg : A ā†’ ĪØ[ xs ā¦‚ A ] (š‘… ā†’ hProp (a ā„“āŠ” ā„“))
--   alg x .fst [] w = Lift (ā„“ ā„“āŠ” a) (w ā‰” 0#) , {!!}
--   alg x .fst (q ā—ƒ y āˆ· xs āŸØ PāŸØxsāŸ© āŸ©) w =
--     āˆ„ ((x ā‰” y) Ɨ āˆƒ p Ɨ (w ā‰” p + q) Ɨ fst (PāŸØxsāŸ© p)) āŠŽ ((x ā‰¢ y) Ɨ fst (PāŸØxsāŸ© w)) āˆ„ , squash
--   alg x .snd .c-set = {!!}
--   alg x .snd .c-dup p q y xs ĻˆāŸØxsāŸ© = funExt Ī» w ā†’ {!!}
--   alg x .snd .c-com p y q z xs ĻˆāŸØxsāŸ© = funExt Ī» w ā†’ {!!}
--   alg x .snd .c-del y xs ĻˆāŸØxsāŸ© = funExt Ī» w ā†’ {!!}




\end{code}
%<*expect-alg>
\begin{code}
āˆ« : (A ā†’ š‘…) ā†’ Ī¦ A š‘…
āˆ« f .fst (p ā—ƒ x āˆ· _ āŸØ āˆ«fxs āŸ©)  = p * f x + āˆ«fxs
āˆ« f .fst []                    = 0#
\end{code}
%</expect-alg>
%<*com>
\begin{code}
āˆ« f .snd .c-com p x q y _ r =
  p * f x + (q * f y + r)
    ā‰”Ė˜āŸØ +-assoc _ _ r āŸ©
  p * f x + q * f y + r
    ā‰”āŸØ cong (_+ r) (+-com _ _) āŸ©
  q * f y + p * f x + r
    ā‰”āŸØ +-assoc _ _ r āŸ©
  q * f y + (p * f x + r) āˆŽ
\end{code}
%</com>
%<*dup>
\begin{code}
āˆ« f .snd .c-dup p q x _ r =
  p * f x + (q * f x + r)
    ā‰”Ė˜āŸØ +-assoc _ _ r āŸ©
  (p * f x + q * f x) + r
    ā‰”Ė˜āŸØ cong (_+ r) (āŸØ+āŸ©* _ _ _) āŸ©
  (p + q) * f x + r āˆŽ
\end{code}
%</dup>
%<*del>
\begin{code}
āˆ« f .snd .c-del x _ r =
  0# * f x + r
    ā‰”āŸØ cong (_+ r) (0* (f x)) āŸ©
  0# + r
    ā‰”āŸØ 0+ r āŸ©
  r āˆŽ
\end{code}
%</del>
\begin{code}
āˆ« f .snd .c-set _ = cIsSet

expect : (A ā†’ š‘…) ā†’ Weighted A ā†’ š‘…
expect f xs = āŸ¦ āˆ« f āŸ§ xs

syntax expect (Ī» x ā†’ e) = āˆ« e š‘‘ x


open import Algebra.SemiringLiterals rng
open import Data.Nat hiding (_+_; _*_)
open import Data.Unit
open import Data.Nat.Literals
open import Literals.Number

_/_ : š‘… ā†’ š‘… ā†’ š‘…
x / y = x
ā…™ : š‘…
ā…™ = 1#


die : Weighted ā„•
\end{code}
%<*die>
\begin{code}
die = ā…™ ā—ƒ 1 āˆ· ā…™ ā—ƒ 2 āˆ· ā…™ ā—ƒ 3 āˆ· ā…™ ā—ƒ 4 āˆ· ā…™ ā—ƒ 5 āˆ· ā…™ ā—ƒ 6 āˆ· []
\end{code}
%</die>
\begin{code}


open import Data.Bool
open import Agda.Builtin.Nat using (_<_)
open import Algebra.SemiringLiterals
open import Data.Unit.UniversePolymorphic

ā„™[3<] : š‘…
\end{code}
%<*p-3>
\begin{code}
ā„™[3<] = (āˆ« if 3 < x then 1 else 0 š‘‘ x) die
\end{code}
%</p-3>
\begin{code}
open import Control.Monad.Weighted.Union rng
\end{code}
%<*int-distrib>
\begin{code}
āˆ«-distrib : āˆ€ (f : A ā†’ š‘…) (ys : Weighted A) ā†’ ĪØ[ xs ā¦‚ A ] āŸ¦ āˆ« f āŸ§ xs + āŸ¦ āˆ« f āŸ§ ys ā‰” āŸ¦ āˆ« f āŸ§ (xs āˆŖ ys)
āˆ«-distrib f ys .fst [] = 0+ (āŸ¦ āˆ« f āŸ§ ys)
āˆ«-distrib f ys .fst (w ā—ƒ x āˆ· xs āŸØ PāŸØxsāŸ© āŸ©) =
  āŸ¦ āˆ« f āŸ§ (w ā—ƒ x āˆ· xs) + āŸ¦ āˆ« f āŸ§ ys    ā‰”āŸØāŸ©
  (w * f x + āŸ¦ āˆ« f āŸ§ xs) + āŸ¦ āˆ« f āŸ§ ys  ā‰”āŸØ +-assoc _ _ _ āŸ©
  w * f x + (āŸ¦ āˆ« f āŸ§ xs + āŸ¦ āˆ« f āŸ§ ys)  ā‰”āŸØ cong (w * f x +_) PāŸØxsāŸ© āŸ©
  w * f x + āŸ¦ āˆ« f āŸ§ (xs āˆŖ ys)          ā‰”āŸØāŸ©
  āŸ¦ āˆ« f āŸ§ (w ā—ƒ x āˆ· xs āˆŖ ys) āˆŽ
āˆ«-distrib f ys .snd = prop-coh Ī» _ ā†’ cIsSet _ _
\end{code}
%</int-distrib>