You can in general not pattern match on functions. That would require computing the inverse, which usually doesn't even exist. You can only match on constructors like Just
or :+
: these are recognisable from ordinary functions / infix operators by starting with an uppercase character or a colon.
You can pattern match on rationals.
import GHC.Real (:%)
test2 :: Rational -> Int
test2 = case x of
0 -> 0
1 :% 2 -> 1
_ -> 2
The reason, I suppose, why it's not really recommended to use :%
(and it's hence only exported from an internal module, not from Data.Ratio
) is that Ratio
values are always supposed to be minimal, but :%
as a plain constructor doesn't ensure this:
Prelude Data.Ratio GHC.Real> 4%2
2 % 1
Prelude Data.Ratio GHC.Real> 4:%2
4 % 2
In particular, if you'd then actually pattern-match on such an unnormalised fraction, you couldn't be sure to succeed.
In cases like 1%2
, you can circumvent the problem by pattern matching on a decimal fraction (finite decimal fractions are unique):
test2 :: Rational -> Int
test2 = case x of
0 -> 0
0.5 -> 1
_ -> 2
Of course, this is perhaps not that nice. In modern Haskell, one could theoretically re-define :%
as a smart pattern synonym:
{-# LANGUAGE PatternSynonyms, ViewPatterns #-}
import Data.Ratio
numDenum :: Integral a => Ratio a -> (a,a)
numDenum x = (numerator x, denominator x)
pattern (:%) :: () => Integral a => a -> a -> Ratio a
pattern a:%b <- (numDenum -> (a,b))
where a:%b = a%b
which could then be used as in your original example.
... but frankly, it's probably better to just use numerator
and denominator
as they are.