module Harmonic.Evaluation.Scoring.Progression
(
ProgressionScore(..)
, ProgressionScoreWeights(..)
, defaultWeights
, defaultWeightsOffline
, scoreProgression
, totalScore
, TransitionMap
, cadenceFavFromMap
, scoreProgressionOnline
, computeCadenceFav
) where
import Control.Monad (forM)
import Data.Foldable (toList)
import qualified Data.Map.Strict as Map
import Data.Map.Strict (Map)
import qualified Data.Text as T
import Data.Text (Text)
import Data.List (nub, sort)
import qualified Database.Bolt as Bolt
import qualified Harmonic.Rules.Types.Progression as Prog
import qualified Harmonic.Rules.Types.ProgressionContext as PC
import qualified Harmonic.Rules.Types.Harmony as H
import qualified Harmonic.Rules.Types.Pitch as P
import qualified Harmonic.Evaluation.Scoring.Dissonance as D
import qualified Harmonic.Evaluation.Scoring.VoiceLeading as VL
import qualified Harmonic.Evaluation.Database.Query as Q
data ProgressionScore = ProgressionScore
{ ProgressionScore -> Double
psRootMotion :: !Double
, ProgressionScore -> Double
psVoiceLeading :: !Double
, ProgressionScore -> Double
psCadenceFav :: !Double
, ProgressionScore -> Double
psModeValidity :: !Double
} deriving (Int -> ProgressionScore -> ShowS
[ProgressionScore] -> ShowS
ProgressionScore -> String
(Int -> ProgressionScore -> ShowS)
-> (ProgressionScore -> String)
-> ([ProgressionScore] -> ShowS)
-> Show ProgressionScore
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ProgressionScore -> ShowS
showsPrec :: Int -> ProgressionScore -> ShowS
$cshow :: ProgressionScore -> String
show :: ProgressionScore -> String
$cshowList :: [ProgressionScore] -> ShowS
showList :: [ProgressionScore] -> ShowS
Show, ProgressionScore -> ProgressionScore -> Bool
(ProgressionScore -> ProgressionScore -> Bool)
-> (ProgressionScore -> ProgressionScore -> Bool)
-> Eq ProgressionScore
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ProgressionScore -> ProgressionScore -> Bool
== :: ProgressionScore -> ProgressionScore -> Bool
$c/= :: ProgressionScore -> ProgressionScore -> Bool
/= :: ProgressionScore -> ProgressionScore -> Bool
Eq)
data ProgressionScoreWeights = ProgressionScoreWeights
{ ProgressionScoreWeights -> Double
wRootMotion :: !Double
, ProgressionScoreWeights -> Double
wVoiceLeading :: !Double
, ProgressionScoreWeights -> Double
wCadenceFav :: !Double
, ProgressionScoreWeights -> Double
wModeValidity :: !Double
} deriving (Int -> ProgressionScoreWeights -> ShowS
[ProgressionScoreWeights] -> ShowS
ProgressionScoreWeights -> String
(Int -> ProgressionScoreWeights -> ShowS)
-> (ProgressionScoreWeights -> String)
-> ([ProgressionScoreWeights] -> ShowS)
-> Show ProgressionScoreWeights
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ProgressionScoreWeights -> ShowS
showsPrec :: Int -> ProgressionScoreWeights -> ShowS
$cshow :: ProgressionScoreWeights -> String
show :: ProgressionScoreWeights -> String
$cshowList :: [ProgressionScoreWeights] -> ShowS
showList :: [ProgressionScoreWeights] -> ShowS
Show, ProgressionScoreWeights -> ProgressionScoreWeights -> Bool
(ProgressionScoreWeights -> ProgressionScoreWeights -> Bool)
-> (ProgressionScoreWeights -> ProgressionScoreWeights -> Bool)
-> Eq ProgressionScoreWeights
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ProgressionScoreWeights -> ProgressionScoreWeights -> Bool
== :: ProgressionScoreWeights -> ProgressionScoreWeights -> Bool
$c/= :: ProgressionScoreWeights -> ProgressionScoreWeights -> Bool
/= :: ProgressionScoreWeights -> ProgressionScoreWeights -> Bool
Eq)
defaultWeights :: ProgressionScoreWeights
defaultWeights :: ProgressionScoreWeights
defaultWeights = ProgressionScoreWeights
{ wRootMotion :: Double
wRootMotion = Double
0.2
, wVoiceLeading :: Double
wVoiceLeading = Double
0.2
, wCadenceFav :: Double
wCadenceFav = Double
0.4
, wModeValidity :: Double
wModeValidity = Double
0.2
}
defaultWeightsOffline :: ProgressionScoreWeights
defaultWeightsOffline :: ProgressionScoreWeights
defaultWeightsOffline = ProgressionScoreWeights
{ wRootMotion :: Double
wRootMotion = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
3
, wVoiceLeading :: Double
wVoiceLeading = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
3
, wCadenceFav :: Double
wCadenceFav = Double
0
, wModeValidity :: Double
wModeValidity = Double
1 Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
3
}
scoreProgression :: PC.ProgressionContext -> ProgressionScore
scoreProgression :: ProgressionContext -> ProgressionScore
scoreProgression ProgressionContext
pc = ProgressionScore
{ psRootMotion :: Double
psRootMotion = Progression -> Double
scoreRootMotion (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
, psVoiceLeading :: Double
psVoiceLeading = Progression -> Double
scoreVoiceLeading (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
, psCadenceFav :: Double
psCadenceFav = Double
0.0
, psModeValidity :: Double
psModeValidity = ProgressionContext -> Double
scoreModeValidity ProgressionContext
pc
}
scoreRootMotion :: Prog.Progression -> Double
scoreRootMotion :: Progression -> Double
scoreRootMotion Progression
prog =
let states :: [CadenceState]
states = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
prog)
n :: Int
n = [CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
states
in if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 then Double
1.0
else
let rootPC :: CadenceState -> Int
rootPC CadenceState
s = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
s))
rootPCs :: [Int]
rootPCs = (CadenceState -> Int) -> [CadenceState] -> [Int]
forall a b. (a -> b) -> [a] -> [b]
map CadenceState -> Int
rootPC [CadenceState]
states
edges :: [(Int, Int)]
edges = [Int] -> [Int] -> [(Int, Int)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int]
rootPCs (Int -> [Int] -> [Int]
forall a. Int -> [a] -> [a]
drop Int
1 [Int]
rootPCs) [(Int, Int)] -> [(Int, Int)] -> [(Int, Int)]
forall a. [a] -> [a] -> [a]
++ [([Int] -> Int
forall a. HasCallStack => [a] -> a
last [Int]
rootPCs, [Int] -> Int
forall a. HasCallStack => [a] -> a
head [Int]
rootPCs)]
rawSum :: Double
rawSum = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Integer -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int -> Integer
D.rootMotionScore ((Int
b Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
a) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12))
| (Int
a, Int
b) <- [(Int, Int)]
edges
] :: Double
avgRaw :: Double
avgRaw = Double
rawSum Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([(Int, Int)] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [(Int, Int)]
edges)
in Double -> Double
clamp01 ((Double
6.0 Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
avgRaw) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
5.0)
vlLowAnchorCal, vlHighAnchorCal :: Double
vlLowAnchorCal :: Double
vlLowAnchorCal = Double
3.0
vlHighAnchorCal :: Double
vlHighAnchorCal = Double
8.0
scoreVoiceLeading :: Prog.Progression -> Double
scoreVoiceLeading :: Progression -> Double
scoreVoiceLeading Progression
prog
| [CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
states Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 = Double
0.5
| Bool
otherwise =
let voicings :: [[Int]]
voicings = (CadenceState -> [Int]) -> [CadenceState] -> [[Int]]
forall a b. (a -> b) -> [a] -> [b]
map CadenceState -> [Int]
honestVoicing [CadenceState]
states
n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
1 ([[Int]] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [[Int]]
voicings)
cost :: Double
cost = Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([[Int]] -> Int
VL.cyclicCost [[Int]]
voicings) :: Double
perEdge :: Double
perEdge = Double
cost Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
in Double -> Double
clamp01 ((Double
vlHighAnchor Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
perEdge) Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
vlHighAnchor Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
vlLowAnchor))
where
states :: [CadenceState]
states = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
prog)
honestVoicing :: CadenceState -> [Int]
honestVoicing CadenceState
cs =
let r :: Int
r = PitchClass -> Int
P.unPitchClass (NoteName -> PitchClass
P.pitchClass (CadenceState -> NoteName
H.stateCadenceRoot CadenceState
cs))
in [Int] -> [Int]
forall a. Ord a => [a] -> [a]
sort [ (PitchClass -> Int
P.unPitchClass PitchClass
i Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
r) Int -> Int -> Int
forall a. Integral a => a -> a -> a
`mod` Int
12
| PitchClass
i <- Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
cs) ]
vlLowAnchor :: Double
vlLowAnchor = Double
vlLowAnchorCal
vlHighAnchor :: Double
vlHighAnchor = Double
vlHighAnchorCal
scoreModeValidity :: PC.ProgressionContext -> Double
scoreModeValidity :: ProgressionContext -> Double
scoreModeValidity ProgressionContext
pc =
case ProgressionContext -> Maybe (Seq (Tristrata, StrataLabel))
PC.pcProvenance ProgressionContext
pc of
Maybe (Seq (Tristrata, StrataLabel))
Nothing -> Double
1.0
Just Seq (Tristrata, StrataLabel)
_ ->
let states :: [CadenceState]
states = Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression (ProgressionContext -> Progression
PC.modeLayer ProgressionContext
pc))
n :: Int
n = [CadenceState] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [CadenceState]
states
in if Int
n Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 then Double
1.0
else let ok :: Int
ok = [()] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ () | CadenceState
s <- [CadenceState]
states
, [PitchClass] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (Cadence -> [PitchClass]
H.cadenceIntervals (CadenceState -> Cadence
H.stateCadence CadenceState
s)) Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
7
]
in Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
ok Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral Int
n
totalScore :: ProgressionScoreWeights -> ProgressionScore -> Double
totalScore :: ProgressionScoreWeights -> ProgressionScore -> Double
totalScore ProgressionScoreWeights
w ProgressionScore
ps =
ProgressionScoreWeights -> Double
wRootMotion ProgressionScoreWeights
w Double -> Double -> Double
forall a. Num a => a -> a -> a
* ProgressionScore -> Double
psRootMotion ProgressionScore
ps
Double -> Double -> Double
forall a. Num a => a -> a -> a
+ ProgressionScoreWeights -> Double
wVoiceLeading ProgressionScoreWeights
w Double -> Double -> Double
forall a. Num a => a -> a -> a
* ProgressionScore -> Double
psVoiceLeading ProgressionScore
ps
Double -> Double -> Double
forall a. Num a => a -> a -> a
+ ProgressionScoreWeights -> Double
wCadenceFav ProgressionScoreWeights
w Double -> Double -> Double
forall a. Num a => a -> a -> a
* ProgressionScore -> Double
psCadenceFav ProgressionScore
ps
Double -> Double -> Double
forall a. Num a => a -> a -> a
+ ProgressionScoreWeights -> Double
wModeValidity ProgressionScoreWeights
w Double -> Double -> Double
forall a. Num a => a -> a -> a
* ProgressionScore -> Double
psModeValidity ProgressionScore
ps
type TransitionMap = Map Text [(H.Cadence, Double)]
cadenceFavFromMap :: TransitionMap -> Prog.Progression -> Double
cadenceFavFromMap :: TransitionMap -> Progression -> Double
cadenceFavFromMap TransitionMap
srcMap Progression
prog =
let cads :: [Cadence]
cads = (CadenceState -> Cadence) -> [CadenceState] -> [Cadence]
forall a b. (a -> b) -> [a] -> [b]
map (Cadence -> Cadence
H.walkTriadCadence (Cadence -> Cadence)
-> (CadenceState -> Cadence) -> CadenceState -> Cadence
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CadenceState -> Cadence
H.stateCadence)
(Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
prog))
n :: Int
n = [Cadence] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Cadence]
cads
in if Int
n Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< Int
2 then Double
0
else
let edges :: [(Cadence, Cadence)]
edges = [Cadence] -> [Cadence] -> [(Cadence, Cadence)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Cadence]
cads (Int -> [Cadence] -> [Cadence]
forall a. Int -> [a] -> [a]
drop Int
1 [Cadence]
cads [Cadence] -> [Cadence] -> [Cadence]
forall a. [a] -> [a] -> [a]
++ [[Cadence] -> Cadence
forall a. HasCallStack => [a] -> a
head [Cadence]
cads])
perEdge :: [Double]
perEdge = ((Cadence, Cadence) -> Double) -> [(Cadence, Cadence)] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (TransitionMap -> (Cadence, Cadence) -> Double
edgeScore TransitionMap
srcMap) [(Cadence, Cadence)]
edges
in [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [Double]
perEdge Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Int -> Double
forall a b. (Integral a, Num b) => a -> b
fromIntegral ([Double] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Double]
perEdge)
edgeScore :: TransitionMap -> (H.Cadence, H.Cadence) -> Double
edgeScore :: TransitionMap -> (Cadence, Cadence) -> Double
edgeScore TransitionMap
srcMap (Cadence
src, Cadence
dst) =
let srcKey :: Text
srcKey = String -> Text
T.pack (Cadence -> String
forall a. Show a => a -> String
show Cadence
src)
dstKey :: Text
dstKey = String -> Text
T.pack (Cadence -> String
forall a. Show a => a -> String
show Cadence
dst)
in case Text -> TransitionMap -> Maybe [(Cadence, Double)]
forall k a. Ord k => k -> Map k a -> Maybe a
Map.lookup Text
srcKey TransitionMap
srcMap of
Maybe [(Cadence, Double)]
Nothing -> Double
0
Just [(Cadence, Double)]
transitions ->
let totalW :: Double
totalW = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum (((Cadence, Double) -> Double) -> [(Cadence, Double)] -> [Double]
forall a b. (a -> b) -> [a] -> [b]
map (Cadence, Double) -> Double
forall a b. (a, b) -> b
snd [(Cadence, Double)]
transitions)
matched :: Double
matched = [Double] -> Double
forall a. Num a => [a] -> a
forall (t :: * -> *) a. (Foldable t, Num a) => t a -> a
sum [ Double
w | (Cadence
c, Double
w) <- [(Cadence, Double)]
transitions
, String -> Text
T.pack (Cadence -> String
forall a. Show a => a -> String
show Cadence
c) Text -> Text -> Bool
forall a. Eq a => a -> a -> Bool
== Text
dstKey ]
in if Double
totalW Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0 Bool -> Bool -> Bool
|| Double
matched Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
<= Double
0
then Double
0
else Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
+ Double
0.5 Double -> Double -> Double
forall a. Num a => a -> a -> a
* (Double
matched Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ Double
totalW)
scoreProgressionOnline
:: Text
-> PC.ProgressionContext
-> Bolt.BoltActionT IO ProgressionScore
scoreProgressionOnline :: Text -> ProgressionContext -> BoltActionT IO ProgressionScore
scoreProgressionOnline Text
seekStr ProgressionContext
pc = do
let basePure :: ProgressionScore
basePure = ProgressionContext -> ProgressionScore
scoreProgression ProgressionContext
pc
Double
cf <- Text -> Progression -> BoltActionT IO Double
computeCadenceFav Text
seekStr (ProgressionContext -> Progression
PC.triadLayer ProgressionContext
pc)
ProgressionScore -> BoltActionT IO ProgressionScore
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure ProgressionScore
basePure { psCadenceFav = cf }
computeCadenceFav
:: Text
-> Prog.Progression
-> Bolt.BoltActionT IO Double
computeCadenceFav :: Text -> Progression -> BoltActionT IO Double
computeCadenceFav Text
seekStr Progression
prog = do
let cads :: [Cadence]
cads = (CadenceState -> Cadence) -> [CadenceState] -> [Cadence]
forall a b. (a -> b) -> [a] -> [b]
map (Cadence -> Cadence
H.walkTriadCadence (Cadence -> Cadence)
-> (CadenceState -> Cadence) -> CadenceState -> Cadence
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CadenceState -> Cadence
H.stateCadence) (Seq CadenceState -> [CadenceState]
forall a. Seq a -> [a]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList (Progression -> Seq CadenceState
Prog.unProgression Progression
prog))
srcKeys :: [Text]
srcKeys = [Text] -> [Text]
forall a. Eq a => [a] -> [a]
nub ((Cadence -> Text) -> [Cadence] -> [Text]
forall a b. (a -> b) -> [a] -> [b]
map (String -> Text
T.pack (String -> Text) -> (Cadence -> String) -> Cadence -> Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Cadence -> String
forall a. Show a => a -> String
show) [Cadence]
cads)
blend :: ComposerWeights
blend = Text -> ComposerWeights
Q.parseComposerWeights Text
seekStr
[(Text, [(Cadence, Double)])]
pairs <- [Text]
-> (Text -> BoltActionT IO (Text, [(Cadence, Double)]))
-> BoltActionT IO [(Text, [(Cadence, Double)])]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [Text]
srcKeys ((Text -> BoltActionT IO (Text, [(Cadence, Double)]))
-> BoltActionT IO [(Text, [(Cadence, Double)])])
-> (Text -> BoltActionT IO (Text, [(Cadence, Double)]))
-> BoltActionT IO [(Text, [(Cadence, Double)])]
forall a b. (a -> b) -> a -> b
$ \Text
k -> do
[(Cadence, ComposerWeights)]
raw <- Text -> BoltActionT IO [(Cadence, ComposerWeights)]
Q.fetchTransitions Text
k
let resolved :: [(Cadence, Double)]
resolved = ComposerWeights
-> [(Cadence, ComposerWeights)] -> [(Cadence, Double)]
Q.resolveWeights ComposerWeights
blend [(Cadence, ComposerWeights)]
raw
(Text, [(Cadence, Double)])
-> BoltActionT IO (Text, [(Cadence, Double)])
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text
k, [(Cadence, Double)]
resolved)
let srcMap :: TransitionMap
srcMap = [(Text, [(Cadence, Double)])] -> TransitionMap
forall k a. Ord k => [(k, a)] -> Map k a
Map.fromList [(Text, [(Cadence, Double)])]
pairs
Double -> BoltActionT IO Double
forall a. a -> BoltActionT IO a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (TransitionMap -> Progression -> Double
cadenceFavFromMap TransitionMap
srcMap Progression
prog)
clamp01 :: Double -> Double
clamp01 :: Double -> Double
clamp01 Double
x
| Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
< Double
0 = Double
0
| Double
x Double -> Double -> Bool
forall a. Ord a => a -> a -> Bool
> Double
1 = Double
1
| Bool
otherwise = Double
x