Skip to content

Add partial applicative typeclass functions #2545

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ADDED: Alongside the existing Eq-like and Ord-like signal operators like `.==.` and `.<=.` etc. There are now new functions for comparing with constants: `.==`, `==.`, `./=`, `/=.`, `.<=`, `<=.`, `.>=`, `>=.`, `.>`, `>.`, `.<`, `<.`, `.&&`, `&&.`, `.||`, `||.`. These are useful for comparing signals with constants in a more readable way. For example, `a .==. pure True` can now be replaced with `a .== True`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ADDED: Alongside the existing Eq-like and Ord-like signal operators like `.==.` and `.<=.` etc. There are now new functions for comparing with constants: `.==`, `==.`, `./=`, `/=.`, `.<=`, `<=.`, `.>=`, `>=.`, `.>`, `>.`, `.<`, `<.`, `.&&`, `&&.`, `.||`, `||.`. These are useful for comparing signals with constants in a more readable way. For example, `a .==. pure True` can now be replaced with `a .== True`.
ADDED: Alongside the existing Eq-like and Ord-like signal operators like `.==.` and `.<=.` etc., there are now new functions for comparing with constants: `.==`, `==.`, `./=`, `/=.`, `.<=`, `<=.`, `.>=`, `>=.`, `.>`, `>.`, `.<`, `<.`, `.&&`, `&&.`, `.||`, `||.`. These are useful for comparing signals with constants in a more readable way. For example, `a .==. pure True` can now be replaced with `a .== True`.

4 changes: 2 additions & 2 deletions clash-prelude/src/Clash/Explicit/Signal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -276,9 +276,9 @@ module Clash.Explicit.Signal
, testFor
-- * Type classes
-- ** 'Eq'-like
, (.==.), (./=.)
, (.==.), (.==), (==.), (./=.), (./=), (/=.)
-- ** 'Ord'-like
, (.<.), (.<=.), (.>=.), (.>.)
, (.<.), (.<), (<.), (.<=.), (.<=), (<=.), (.>=.), (.>=), (>=.), (.>.), (.>), (>.)
-- * Bisignal functions
, veryUnsafeToBiSignalIn
, readFromBiSignal
Expand Down
4 changes: 2 additions & 2 deletions clash-prelude/src/Clash/Signal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -241,9 +241,9 @@ module Clash.Signal
, testFor
-- * Type classes
-- ** 'Eq'-like
, (.==.), (./=.)
, (.==.), (.==), (==.), (./=.), (./=), (/=.)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's further up in this file, but the new functions amongst (.&&.), (&&.), (.&&), (.||.), (||.), (.||) should also be imported.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exported*

-- ** 'Ord'-like
, (.<.), (.<=.), (.>=.), (.>.)
, (.<.), (.<), (<.), (.<=.), (.<=), (<=.), (.>=.), (.>=), (>=.), (.>.), (.>), (>.)
-- * Bisignal functions
, veryUnsafeToBiSignalIn
, readFromBiSignal
Expand Down
199 changes: 196 additions & 3 deletions clash-prelude/src/Clash/Signal/Internal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ module Clash.Signal.Internal
, resetGen
, resetGenN
-- * Boolean connectives
, (.&&.), (.||.)
, (.&&.), (&&.), (.&&), (.||.), (||.), (.||)
-- * Simulation functions (not synthesizable)
, simulate
-- ** lazy version
Expand All @@ -157,9 +157,9 @@ module Clash.Signal.Internal
, testFor
-- * Type classes
-- ** 'Eq'-like
, (.==.), (./=.)
, (.==.), (.==), (==.), (./=.), (./=), (/=.)
-- ** 'Ord'-like
, (.<.), (.<=.), (.>=.), (.>.)
, (.<.), (.<), (<.), (.<=.), (.<=), (<=.), (.>=.), (.>=), (>=.), (.>.), (.>), (>.)
-- ** 'Functor'
, mapSignal#
-- ** 'Applicative'
Expand Down Expand Up @@ -1421,6 +1421,30 @@ infixr 2 .||.
(.||.) :: Applicative f => f Bool -> f Bool -> f Bool
(.||.) = liftA2 (||)

infix 2 .||
-- | The above type is a generalization for:
--
-- @
-- __(.||)__ :: 'Ord' a => 'Clash.Signal.Signal' Bool -> 'Bool' -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('||') that allows comparing a @'Clash.Signal.Signal' Bool@ with a constant
-- @Bool@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.||) :: Functor f => f Bool -> Bool -> f Bool
a .|| b = fmap (|| b) a

infixr 2 ||.
-- | The above type is a generalization for:
--
-- @
-- __(||.)__ :: 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('||') that allows comparing a constant @Bool@ with a @'Clash.Signal.Signal' Bool@
-- and returns a 'Clash.Signal.Signal' of 'Bool'
(||.) :: Functor f => Bool -> f Bool -> f Bool
a ||. b = fmap (a ||) b

infixr 3 .&&.
-- | The above type is a generalization for:
--
Expand All @@ -1432,6 +1456,30 @@ infixr 3 .&&.
(.&&.) :: Applicative f => f Bool -> f Bool -> f Bool
(.&&.) = liftA2 (&&)

infixr 3 .&&
-- | The above type is a generalization for:
--
-- @
-- __(.&&)__ :: 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('&&') that allows comparing a @'Clash.Signal.Signal' Bool@ with a
-- constant @Bool@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.&&) :: (Functor f) => f Bool -> Bool -> f Bool
(.&&) a b = fmap (&& b) a

infixr 3 &&.
-- | The above type is a generalization for:
--
-- @
-- __(&&.)__ :: 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool' -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('&&') that allows comparing a constant @'Bool@ with a
-- @'Clash.Signal.Signal' Bool@ and returns a 'Clash.Signal.Signal' of 'Bool'
(&&.) :: (Functor f) => Bool -> f Bool -> f Bool
(&&.) a b = fmap (a &&) b

-- [Note: register strictness annotations]
--
-- In order to produce the first (current) value of the register's output
Expand Down Expand Up @@ -1611,6 +1659,30 @@ infix 4 .==.
(.==.) :: (Eq a, Applicative f) => f a -> f a -> f Bool
(.==.) = liftA2 (==)

infix 4 .==
-- | The above type is a generalization for:
--
-- @
-- __(.==)__ :: 'Eq' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('==') that allows comparing a @'Clash.Signal.Signal' a@ with a
-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.==) :: (Eq a, Functor f) => f a -> a -> f Bool
(.==) a b = fmap (==b) a

infix 4 ==.
-- | The above type is a generalization for:
--
-- @
-- __(==.)__ :: 'Eq' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('==') that allows comparing a @'Clash.Signal.Signal' a@ with a
-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(==.) :: (Eq a, Functor f) => a -> f a -> f Bool
(==.) a b = fmap (a==) b

infix 4 ./=.
-- | The above type is a generalization for:
--
Expand All @@ -1622,6 +1694,31 @@ infix 4 ./=.
(./=.) :: (Eq a, Applicative f) => f a -> f a -> f Bool
(./=.) = liftA2 (/=)

infix 4 ./=
-- | The above type is a generalization for:
--
-- @
-- __(./=)__ :: 'Eq' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('/=') that allows comparing a @'Clash.Signal.Signal' a@ with a
-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(./=) :: (Eq a, Functor f) => f a -> a -> f Bool
(./=) a b = fmap (/=b) a

infix 4 /=.
-- | The above type is a generalization for:
--
-- @
-- __(/=.)__ :: 'Eq' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('/=') that allows comparing a @'Clash.Signal.Signal' a@ with a
-- constant @a@ and returns a 'Clash.Signal.Signal' of 'Bool'

(/=.) :: (Eq a, Functor f) => a -> f a -> f Bool
(/=.) a b = fmap (a /=) b

infix 4 .<.
-- | The above type is a generalization for:
--
Expand All @@ -1633,6 +1730,30 @@ infix 4 .<.
(.<.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
(.<.) = liftA2 (<)

infix 4 <.
-- | The above type is a generalization for:
--
-- @
-- __(<.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('<') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(<.) :: (Ord a, Functor f) => a -> f a -> f Bool
(<.) a b = fmap (a<) b

infix 4 .<
-- | The above type is a generalization for:
--
-- @
-- __(.<)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('<') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.<) :: (Ord a, Functor f) => f a -> a -> f Bool
(.<) a b = fmap (<b) a

infix 4 .<=.
-- | The above type is a generalization for:
--
Expand All @@ -1644,6 +1765,30 @@ infix 4 .<=.
(.<=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
(.<=.) = liftA2 (<=)

infix 4 .<=
-- | The above type is a generalization for:
--
-- @
-- __(.<=)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('GHC.TypeNats.<=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.<=) :: (Ord a, Functor f) => f a -> a -> f Bool
(.<=) a b = fmap (<=b) a

infix 4 <=.
-- | The above type is a generalization for:
--
-- @
-- __(<=.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('GHC.TypeNats.<=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(<=.) :: (Ord a, Functor f) => a -> f a -> f Bool
(<=.) a b = fmap (a<=)b

infix 4 .>.
-- | The above type is a generalization for:
--
Expand All @@ -1655,6 +1800,30 @@ infix 4 .>.
(.>.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
(.>.) = liftA2 (>)

infix 4 .>
-- | The above type is a generalization for:
--
-- @
-- __(.>)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('>') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.>) :: (Ord a, Functor f) => f a -> a -> f Bool
(.>) a b = fmap (>b) a

infix 4 >.
-- | The above type is a generalization for:
--
-- @
-- __(>.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('>') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(>.) :: (Ord a, Functor f) => a -> f a -> f Bool
(>.) a b = fmap (a>) b

infix 4 .>=.
-- | The above type is a generalization for:
--
Expand All @@ -1666,6 +1835,30 @@ infix 4 .>=.
(.>=.) :: (Ord a, Applicative f) => f a -> f a -> f Bool
(.>=.) = liftA2 (>=)

infix 4 .>=
-- | The above type is a generalization for:
--
-- @
-- __(.>=)__ :: 'Ord' a => 'Clash.Signal.Signal' a -> a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('>=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(.>=) :: (Ord a, Functor f) => f a -> a -> f Bool
(.>=) a b = fmap (>=b) a

infix 4 >=.
-- | The above type is a generalization for:
--
-- @
-- __(>=.)__ :: 'Ord' a => a -> 'Clash.Signal.Signal' a -> 'Clash.Signal.Signal' 'Bool'
-- @
--
-- It is a version of ('>=') that allows comparing a @'Clash.Signal.Signal' a@ with a constant
-- @a@ and returns a 'Clash.Signal.Signal' of 'Bool'
(>=.) :: (Ord a, Functor f) => a -> f a -> f Bool
(>=.) a b = fmap (a>=) b

instance Fractional a => Fractional (Signal dom a) where
(/) = liftA2 (/)
recip = fmap recip
Expand Down
2 changes: 1 addition & 1 deletion clash-prelude/tests/Clash/Tests/BlockRam.hs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ readRam
:: (HiddenClockResetEnable dom)
=> Signal dom (Unsigned 4)
-> Signal dom (Unsigned 8)
readRam addr = mux (register False $ addr .<. 8) ram (pure 0xff)
readRam addr = mux (register False $ addr .< 8) ram (pure 0xff)
where
ram = blockRam1 NoClearOnReset (SNat @8) 0 addr (pure Nothing)

Expand Down
2 changes: 1 addition & 1 deletion clash-prelude/tests/Clash/Tests/Ram.hs
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ ram rd we wr din =

maskOobRead :: Ram
maskOobRead rd we wr din =
maybeIsX <$> mux (rd .<. 2) ram0 (pure 4)
maybeIsX <$> mux (rd .< 2) ram0 (pure 4)
where
ram0 = asyncRam# clockGen clockGen enableGen d2 rd we wr din

Expand Down
2 changes: 1 addition & 1 deletion tests/shouldfail/Verification/NonTemporal.hs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ assertCvResult
assertCvResult clk rst gen max results = done
where
counter = register clk rst gen (minBound :: n) (succ <$> counter)
done = hideAssertion results (counter .==. pure maxBound)
done = hideAssertion results (counter .== maxBound)
{-# INLINE assertCvResult #-}

binaryTest
Expand Down
2 changes: 1 addition & 1 deletion tests/shouldwork/Basic/AES.hs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ aes
-> Signal dom (BitVector 128)
-> Signal dom (BitVector 128)
-> Signal dom (Unsigned 4, Vec 4 (BitVector 32), BitVector 128, Bool)
aes start key block = bundle (cnt, roundKey, pack <$> roundState, cnt .==. 11)
aes start key block = bundle (cnt, roundKey, pack <$> roundState, cnt .== 11)
where

roundKey :: Signal dom (Vec 4 (BitVector 32))
Expand Down
10 changes: 2 additions & 8 deletions tests/shouldwork/Issues/T1187/Utils.hs
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{-# LANGUAGE ScopedTypeVariables #-}
module T1187.Utils
( (.==)

, debounce
( debounce

, roundRobin

Expand All @@ -25,18 +23,14 @@ debounce _ initial this = regEn initial stable this
where
counter = register (0 :: Index (ClockDivider dom ps)) counter'
counter' = mux (unchanged initial this) counter 0
stable = counter' .==. pure maxBound
stable = counter' .== maxBound

roundRobin
:: forall n dom. (KnownNat n, HiddenClockResetEnable dom)
=> Signal dom Bool
-> (Signal dom (Vec n Bool), Signal dom (Index n))
roundRobin _next = undefined

infix 4 .==
(.==) :: (Eq a, Functor f) => f a -> a -> f Bool
fx .== y = (== y) <$> fx

moreIdx :: (Eq a, Enum a, Bounded a) => a -> a
moreIdx = fromMaybe maxBound . succIdx

Expand Down
4 changes: 2 additions & 2 deletions tests/shouldwork/Xilinx/ClockWizard.hs
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ testBench ::
testBench = done
where
(o1, o2) = unbundle $ topEntity clkSE clkDiff rst
done1 = o1 .==. pure maxBound
done2 = o2 .==. pure maxBound
done1 = o1 .== maxBound
done2 = o2 .== maxBound
done = unsafeSynchronizer clockGen clkSE $ fmap endVhdlSim $
strictAnd <$> done1 <*> done2
strictAnd !a !b = a && b
Expand Down