{-# LANGUAGE RebindableSyntax #-}
module Copilot.Library.Voting
( majority, aMajority ) where
import Copilot.Language
import qualified Prelude as P
majority :: (P.Eq a, Typed a) =>
[Stream a]
-> Stream a
majority :: forall a. (Eq a, Typed a) => [Stream a] -> Stream a
majority [] = forall a. String -> a
badUsage String
"majority: empty list not allowed"
majority (Stream a
x:[Stream a]
xs) = forall a.
(Eq a, Typed a) =>
[Stream a] -> Stream a -> Stream Word32 -> Stream a
majority' [Stream a]
xs Stream a
x Stream Word32
1
majority' :: (P.Eq a, Typed a)
=> [Stream a] -> Stream a -> Stream Word32 -> Stream a
majority' :: forall a.
(Eq a, Typed a) =>
[Stream a] -> Stream a -> Stream Word32 -> Stream a
majority' [] Stream a
can Stream Word32
_ = Stream a
can
majority' (Stream a
x:[Stream a]
xs) Stream a
can Stream Word32
cnt =
forall a b.
(Typed a, Typed b) =>
Stream a -> (Stream a -> Stream b) -> Stream b
local (Stream Word32
cnt forall a. (Eq a, Typed a) => Stream a -> Stream a -> Stream Bool
== Stream Word32
0) Stream Bool -> Stream a
inZero
where
inZero :: Stream Bool -> Stream a
inZero Stream Bool
zero = forall a b.
(Typed a, Typed b) =>
Stream a -> (Stream a -> Stream b) -> Stream b
local (if Stream Bool
zero then Stream a
x else Stream a
can) Stream a -> Stream a
inCan
where
inCan :: Stream a -> Stream a
inCan Stream a
can' =
case [Stream a]
xs of
[] -> Stream a
can'
[Stream a]
_ -> forall a b.
(Typed a, Typed b) =>
Stream a -> (Stream a -> Stream b) -> Stream b
local (if Stream Bool
zero Stream Bool -> Stream Bool -> Stream Bool
|| Stream a
x forall a. (Eq a, Typed a) => Stream a -> Stream a -> Stream Bool
== Stream a
can then Stream Word32
cntforall a. Num a => a -> a -> a
+Stream Word32
1 else Stream Word32
cntforall a. Num a => a -> a -> a
-Stream Word32
1) Stream Word32 -> Stream a
inCnt
where
inCnt :: Stream Word32 -> Stream a
inCnt Stream Word32
cnt' = forall a.
(Eq a, Typed a) =>
[Stream a] -> Stream a -> Stream Word32 -> Stream a
majority' [Stream a]
xs Stream a
can' Stream Word32
cnt'
aMajority :: (P.Eq a, Typed a) =>
[Stream a]
-> Stream a
-> Stream Bool
aMajority :: forall a. (Eq a, Typed a) => [Stream a] -> Stream a -> Stream Bool
aMajority [] Stream a
_ = forall a. String -> a
badUsage String
"aMajority: empty list not allowed"
aMajority [Stream a]
xs Stream a
can =
let
cnt :: Stream Word32
cnt = forall a.
(Eq a, Typed a) =>
Stream Word32 -> [Stream a] -> Stream a -> Stream Word32
aMajority' Stream Word32
0 [Stream a]
xs Stream a
can
in
(Stream Word32
cnt forall a. Num a => a -> a -> a
* Stream Word32
2) forall a. (Ord a, Typed a) => Stream a -> Stream a -> Stream Bool
> forall a b. (Integral a, Num b) => a -> b
fromIntegral (forall (t :: * -> *) a. Foldable t => t a -> Int
length [Stream a]
xs)
aMajority' :: (P.Eq a, Typed a)
=> Stream Word32 -> [Stream a] -> Stream a -> Stream Word32
aMajority' :: forall a.
(Eq a, Typed a) =>
Stream Word32 -> [Stream a] -> Stream a -> Stream Word32
aMajority' Stream Word32
cnt [] Stream a
_ = Stream Word32
cnt
aMajority' Stream Word32
cnt (Stream a
x:[Stream a]
xs) Stream a
can =
forall a b.
(Typed a, Typed b) =>
Stream a -> (Stream a -> Stream b) -> Stream b
local (if Stream a
x forall a. (Eq a, Typed a) => Stream a -> Stream a -> Stream Bool
== Stream a
can then Stream Word32
cntforall a. Num a => a -> a -> a
+Stream Word32
1 else Stream Word32
cnt) forall a b. (a -> b) -> a -> b
$ \ Stream Word32
cnt' ->
forall a.
(Eq a, Typed a) =>
Stream Word32 -> [Stream a] -> Stream a -> Stream Word32
aMajority' Stream Word32
cnt' [Stream a]
xs Stream a
can