How to implement `Constraint` reflection? [Ad-Hoc polymorphism based on available Constraints] - haskell

For example, with types, you can implement AdHoc polymorphism using Typeable to define a different behavior depending on what the input type is:
foo :: forall a. Typeable a => a -> a
foo | Just HRefl <- typeRep #a `eqTypeRep` typeRep #Bool = not
| otherwise = id
-- >>> foo 3
3
-- >>> foo True
False
I would like to do something similar to that but instead check if a type has a curtain instance of a Constraint, and implement a different behavior on that.
So far I have looked at two packages, Data.Constraint and Data.Exists. I think the solution lies with one of them but I have not been able to understand how I would go about doing this.
For context, this came about when I was thinking about what a polymorphic safe integer division function would look like
polymorphicSafeDiv :: Integral a => a -> a -> Maybe a
polymorphicSafeDiv x y = undefined
If I want this function to work for both bounded and unbounded Integrals I need to consider both, division by zero, and the overflow scenario for minBound #Int / (-1). I would imagine something like
polymorphicSafeDiv :: Integral a => a -> a -> Maybe a
polymorphicSafeDiv x y
| y == 0 = Nothing
| y == (-1) = case (???) of
Just Relf -> Nothing
_ -> Just $ x `div` y
| otherwise = Just $ x `div` y

The idiomatic way to do this is to make a new class.
class LowerBound a where lowerBound :: Maybe a
instance LowerBound Int where lowerBound = Just minBound
instance LowerBound Integer where lowerBound = Nothing
polymorphicSafeDiv :: (LowerBound a, Integral a) => a -> a -> Maybe a
polymorphicSafeDiv x = \case
0 -> Nothing
-1 -> case lowerBound of
Just lb | x == lb -> Nothing
_ -> Just (x `div` y)
y -> Just (x `div` y)
Actually, I'm not sure LowerBound is a great name for this. For example, Word has a lower bound, but dividing it by other things shouldn't produce Nothing. Perhaps you should make a division class directly.
class Integral a => SafeDivide a where
safeDiv :: a -> a -> Maybe a
default safeDiv :: Bounded a => a -> a -> Maybe a
safeDiv x = \case
-1 | x == minBound -> Nothing
y -> testZeroDiv x y
testZeroDiv :: Integral a => a -> a -> Maybe a
testZeroDiv x = \case
0 -> Nothing
y -> Just (x `div` y)
instance SafeDivide Int
instance SafeDivide Integer where safeDiv = testZeroDiv
instance SafeDivide Word where safeDiv = testZeroDiv

Related

Haskell type declaration problem with isSquareNumber function

I have to write a function that determines if a number is a perfect square, which I was able to do:
isSquareNumber x
| x < 0 = False
| otherwise = snd (properFraction (sqrt x)) == 0.0
But I have to use a given type declaration: isSquareNumber :: Int -> Bool
Whitout it, it works fine, but when I add it I get errors.
sqrt :: Floating a => a -> a does not work with an Int, but with Floating types, and an Int is not an Floating type.
You can use fromIntegral :: (Integral a, Num b) => a -> b to convert an Integral type to any Num type. You thus can implement this as:
isSquareNumber :: Int -> Bool
isSquareNumber x = x >= 0 && f == 0.0
where (_, f) = properFraction (sqrt (fromIntegral x))

Type signatures that never make sense

Consider
(a->a) -> [a] -> Bool
Is there any meaningful definition for this signature? That is, a definition that not simply ignores the argument?
x -> [a] -> Bool
It seems there are many such signatures that can be ruled out immediately.
Carsten König suggested in a comment to use the free theorem. Let's try that.
Prime the cannon
We start by generating the free theorem corresponding to the type (a->a) -> [a] -> Bool. This is a property that every function with that type must satisfy, as established by the famous Wadler's paper Theorems for free!.
forall t1,t2 in TYPES, R in REL(t1,t2).
forall p :: t1 -> t1.
forall q :: t2 -> t2.
(forall (x, y) in R. (p x, q y) in R)
==> (forall (z, v) in lift{[]}(R). f_{t1} p z = f_{t2} q v)
lift{[]}(R)
= {([], [])}
u {(x : xs, y : ys) | ((x, y) in R) && ((xs, ys) in lift{[]}(R))}
An example
To better understand the theorem above, let's run over a concrete example. To use the theorem, we need to take any two types t1,t2, so we can pick t1=Bool and t2=Int.
Then we need to choose a function p :: Bool -> Bool (say p=not), and a function q :: Int -> Int (say q = \x -> 1-x).
Now, we need to define a relation R between Bools and Ints. Let's take the standard boolean
<->integer correspondence, i.e.:
R = {(False,0),(True,1)}
(the above is a one-one correspondence, but it does not have to be, in general).
Now we need to check that (forall (x, y) in R. (p x, q y) in R). We only have two cases to check for (x,y) in R:
Case (x,y) = (False,0): we verify that (not False, 1-0) = (True, 1) in R (ok!)
Case (x,y) = (True ,1): we verify that (not True , 1-1) = (False,0) in R (ok!)
So far so good. Now we need to "lift" the relation so to work on lists: e.g.
[True,False,False,False] is in relation with [1,0,0,0]
This extended relation is the one named lift{[]}(R) above.
Finally, the theorem states that, for any function f :: (a->a) -> [a] -> Bool we must have
f_Bool not [True,False,False,False] = f_Int (\x->1-x) [1,0,0,0]
where above f_Bool simply makes it explicit that f is used in the specialised case in which a=Bool.
The power of this lies in that we do not know what the code of f actually is. We are deducing what f must satisfy by only looking at its polymorphic type.
Since we get types from type inference, and we can turn types into theorems, we really get "theorems for free!".
Back to the original goal
We want to prove that f does not use its first argument, and that it does not care about its second list argument, either, except for its length.
For this, take R be the universally true relation. Then, lift{[]}(R) is a relation which relates two lists iff they have the same length.
The theorem then implies:
forall t1,t2 in TYPES.
forall p :: t1 -> t1.
forall q :: t2 -> t2.
forall z :: [t1].
forall v :: [t2].
length z = length v ==> f_{t1} p z = f_{t2} q v
Hence, f ignores the first argument and only cares about the length of the second one.
QED
You can't do anything interesting with x on it's own.
You can do stuff with [x]; for example, you can count how many nodes are in the list. So, for example,
foo :: (a -> a) -> [a] -> Bool
foo _ [] = True
foo _ (_:_) = False
bar :: x -> [a] -> Bool
bar _ [] = True
bar _ (_:_) = False
If you have an x and a function that turns an x into something else, you can do interesting stuff:
big :: (x -> Int) -> x -> Bool
big f n = if f n > 10 then True else False
If x belongs to some type class, then you can use all the methods of that class on it. (This is really a special-case of the previous one.)
double :: Num x => x -> x
double = (2*)
On the other hand, there are plenty of type signatures for which no valid functions exist:
magic :: x -> y
magic = -- erm... good luck with that!
I read somewhere that the type signatures involving only variables for which a real function exists are exactly the logical theorems that are true. (I don't know the name for this property, but it's quite interesting.)
f1 :: (x -> y) -> x -> y
-- Given that X implies Y, and given that X is true, then Y is true.
-- Well, duh.
f2 :: Either (x -> y) (x -> z) -> x -> Either y z
-- Given that X implies Y or X implies Z, and given X, then either Y or Z is true.
-- Again, duh.
f3 :: x -> y
-- Given that X is true, then any Y is true.
-- Erm, no. Just... no.

How does Haskell infer definitions for type classes?

So I am playing around with Haskell and noticed something which puzzles me. I defined a complex floating point data structure and wanted to used comparison operators on it. Initally I did this which worked fine:
data Cplx = Cplx Float Float deriving (Eq, Show)
instance Ord Cplx where
(<=) a b = (<=) (normCplx a) (normCplx b)
(>=) a b = (>=) (normCplx a) (normCplx b)
(<) a b = (<) (normCplx a) (normCplx b)
(>) a b = (>) (normCplx a) (normCplx b)
normCplx :: Cplx -> Float
normCplx (Cplx a1 a2) = sqrt( a1^2 + a2^2)
But I also noticed just declaring:
data Cplx = Cplx Float Float deriving (Eq, Show)
instance Ord Cplx where
(<=) a b = (<=) (normCplx a) (normCplx b)
normCplx :: Cplx -> Float
normCplx (Cplx a1 a2) = sqrt( a1^2 + a2^2)
Also got the job done just fine. How does Haskell infer the definitons for the other comparison operators given only the single definition?
Thanks!
the rest is implemented just with the type-class using (<=) (or compare) - this is what "minimal implementation" in the docs here: http://hackage.haskell.org/package/base-4.7.0.1/docs/Prelude.html#t:Ord mean.
Minimal complete definition: either compare or <=. Using compare can
be more efficient for complex types.
Sadly in this case you cannot show the source directly from Hackage but as Ord a implies Eq a it's not hard to imagine how this is done.
For example as you have (<=) implemented (<) can just be:
a < b = a /= b && a <= b
with that you get
a >= b = not (a < b)
and finaly
a > b = not (a <= b)
or something similar.
Btw as you might have seen in your first implementation you did not implement compare, max or min even if it's part of the type-class and this it got infered too.
Maybe you can try to guess it yourself.
remark
David found the sources - here is the implementation right from there:
class (Eq a) => Ord a where
compare :: a -> a -> Ordering
(<), (<=), (>), (>=) :: a -> a -> Bool
max, min :: a -> a -> a
compare x y = if x == y then EQ
-- NB: must be '<=' not '<' to validate the
-- above claim about the minimal things that
-- can be defined for an instance of Ord:
else if x <= y then LT
else GT
x < y = case compare x y of { LT -> True; _ -> False }
x <= y = case compare x y of { GT -> False; _ -> True }
x > y = case compare x y of { GT -> True; _ -> False }
x >= y = case compare x y of { LT -> False; _ -> True }
-- These two default methods use '<=' rather than 'compare'
-- because the latter is often more expensive
max x y = if x <= y then y else x
min x y = if x <= y then x else y
{-# MINIMAL compare | (<=) #-}
As you can see: if you have compare or (<=) all else follows.
It must be said that the Ord typeclass is for types with total order, and complex numbers do not satisfy the properties of total order. In particular, your implementation violates the anti-symmetry property, that is,
forall a b. if a ≤ b and b ≤ a then a = b.
Failing to satisfy this property violates the contract of Ord and could result in strange bugs, depending on how the instance is used.
It might be more appropriate to apply normCplx where you might have relied on functionality derived from Ord, e.g., sortBy (compare `on` normCplx) where you might have just used sort.

Newtons Method Type Class Haskell

Trying a couple different ways of implementing Newtons Method, but I cant seem to get it working. It's most likely a very simple fix, but I just need someone to point out what I'm doing wrong. Yeah I know my code is ugly, just messing around right now.
In this example, I just try to make an equation for xn+1, which isn't working.
function :: (Num a) => a -> a
function x = 98 - x^98
function' :: (Num a) => a -> a
function' x = (-98)*(x^97)
xi = 1.04
iterations = 20
newtons :: (Integral a) => a -> a
newtons x = x - fromIntegral ( div (function x) (function' x) )
When I type 'newtons xi' in ghci I get an error that says "no instance for Integral Double arising from a use of newtons". What type class should I be using to make this work?
Just needed more general types. Didn't see the iteration function which is the core of the algorithm so I tried to adapt it around your existing code:
function :: Num a => a -> a
function x = 98 - x^98
function' :: Num a => a -> a
function' x = (-98)*(x^97)
xi :: Double
xi = 1.04
newton :: (Fractional a, Ord a) => (a -> a) -> (a -> a) -> a -> a
newton f f' x
| (abs (f x)) < epsilon = x
| otherwise = newton f f' (x - (f x / f' x))
where
epsilon = 1e-4
main :: IO ()
main = do
-- Prints out the two extrema
print $ newton function function' xi -- 1.0478970878235732
print $ newton function function' (-xi) -- -1.0478970878235732
This is a naive implementation, if you need performance and numeric stability then the ad package is best suited for this.

Understanding multiple types/typeclasses in Haskell declarations

I'm trying to learn Haskell with Learn You A Haskell... but I got impatient and wanted to implement a favorite algorithm of mine to see if I could.
I'm working on the tortoise/hare algorithm (Floyd's algorithm) for cycle detection.
Here's the code I have so far:
idx :: (Eq a) => (a -> a) -> a -> a -> a
idx f tortoise hare
| (f tortoise) == (f (f hare)) = (f f hare)
| otherwise = (idx f) (f tortoise) (f f hare)
mu :: (Eq a) => (a -> a) -> a -> a -> Integer -> (Integer, a)
mu f tortoise hare cntr
| (f tortoise) == (f hare) = (cntr+1, f tortoise)
| otherwise = (mu f) (f tortoise) (f hare) (cntr+1)
lam :: (Eq a) => (a -> a) -> a -> a -> Integer -> Integer
lam f tortoise hare cntr
| tortoise == hare = cntr+1
| otherwise = (lam f) tortoise (f hare) (cntr+1)
floyd :: (Eq a) => (a -> a) -> a -> (Integer, Integer)
floyd f x0 =
let z = (idx f) x0 x0
(y1, t) = (mu f) x0 z 0
y2 = (lam f) t (f t) 0
in (y1, y2)
tester :: (Integer a) => a -> a
tester a
| a == 0 = 2
| a == 2 = 6
| a == 6 = 1
| a == 1 = 3
| a == 3 = 6
| a == 4 = 0
| a == 5 = 1
| otherwise = error "Input must be between 0 and 6"
(floyd tester) 0
This tries to break the logic up into three steps. First get the index where f_idx == f_{2*idx}, then move from the start to get the parameter mu (distance from first element to start of the cycle), then move until you hit a repeat (length of the cycle).
The function floyd is my hacky attempt to put these together.
Aside from this being somewhat un-functional, I am also having issues loading the module and I'm not sure why:
Prelude> :load M:\papers\programming\floyds.hs
[1 of 1] Compiling Main ( M:\papers\programming\floyds.hs, interpreted )
M:\papers\programming\floyds.hs:23:12:
`Integer' is applied to too many type arguments
In the type signature for `tester': tester :: Integer a => a -> a
Failed, modules loaded: none.
Changing all occurrences of Integer to Int or Num don't make it any better.
I'm not understanding the mis-application of Int. Following along in the tutorial, most type declarations for functions always have the form
function_name :: (Some_Type a) => <stuff involving a and possibly other types>
But when I replace the (Eq a) with (Num a) or (Int a) I get a similar error (type applied to too many arguments).
I tried reading this, but it disagrees with the tutorial's notation (e.g. almost every function defined in these examples).
I must be badly misunderstanding Types vs. TypeClasses, but that's precisely what I thought I did understand to lead me to make the type declarations as in my code above.
A follow up might be: what is the syntax for have multiple TypeClasses in the function type declaration? Something like:
mu :: (Eq a, Int b) => (a -> a) -> a -> a -> b -> (b, a)
(but this also gave compile errors saying Int was applied to too many arguments).
Added
Cleaned up and with changes based on the answer, the code below appears to be working:
idx :: (Eq a) => (a -> a) -> a -> a -> a
idx f tortoise hare
| (f tortoise) == (f (f hare)) = (f (f hare))
| otherwise = (idx f) (f tortoise) (f (f hare))
mu :: (Eq a) => (a -> a) -> a -> a -> Integer -> (Integer, a)
mu f tortoise hare cntr
| (f tortoise) == (f hare) = (cntr+1, (f tortoise))
| otherwise = (mu f) (f tortoise) (f hare) (cntr+1)
lam :: (Eq a) => (a -> a) -> a -> a -> Integer -> Integer
lam f tortoise hare cntr
| tortoise == hare = cntr+1
| otherwise = (lam f) tortoise (f hare) (cntr+1)
floyd :: (Eq a) => (a -> a) -> a -> (Integer, Integer)
floyd f x0 =
let z = (idx f) x0 x0
(y1, t) = (mu f) x0 z 0
y2 = (lam f) t (f t) 0
in (y1, y2)
tester :: (Integral a) => a -> a
tester a
| a == 0 = 2
| a == 2 = 6
| a == 6 = 1
| a == 1 = 3
| a == 3 = 6
| a == 4 = 0
| a == 5 = 1
| otherwise = error "Input must be between 0 and 6"
Then I see
*Main> floyd tester 2
(1,3)
and given this test function (essentially like the one from the Wikipedia example), this makes sense. If you start a x0 = 2 then the sequence is 2 -> 6 -> 1 -> 3 -> 6..., so mu is 1 (you have to move in one element to hit the start of the sequence) and lam is 3 (the sequence repeats every three entries).
I suppose there's some question about whether to always consider the first point as burn-in before you can possibly "repeat".
If anyone has advice on this, I'd be grateful. In particular, my cntr construct seems un-functional to me.. it's a way of counting how many repeated calls are made. I'm not sure if there's a better/different way that's less like saving the state of a variable.
You can't say Integer a or Int a. You probably mean Integral a. Integral encompasses all types that are integers of some kind, including Integer and Int.
The thing before => is not a type but a type class. SomeTypeClass a => a means "any type a that is a member of the type class SomeTypeClass".
You can do this:
function :: Int -> String
which is a function that takes an Int and returns a String. You can also do this:
function :: Integer -> String
which is a function that takes an Integer and returns a String. You can also do this:
function :: Integral i => i -> String
which is a function that takes either an Int, or an Integer, or any other integer-like type and returns a String.
About your second question, your guess is right. You coud do
mu :: (Eq a, Integral b) => (a -> a) -> a -> a -> b -> (b, a)
Your commented questions:
1. what do you do if you want to ensure something has a Type that is a member of multiple TypeClasses?
You could do something like
function :: (Show a, Integral a) => a -> String
That will restrict a to be any type that is both a member of Show and Integral.
2. Suppose you only want to restrict the Type to reside in a TypeClass for some of the arguments, and you want other arguments to be of specific Types?
Then you just write out the other arguments as specific types. You could do
function :: (Integral a) -> a -> Int -> String
which takes any integer-like type a, and then an Int and returns a String.
The general form of a (Rank-1) type declaration is
x :: [forall a b … . ] Cᴏɴꜱᴛʀᴀɪɴᴛ(a, b, …) => Sɪɢɴᴀᴛᴜʀᴇ(a, b, …)
where
The forall a b … brings type variables in scope. This is usually omitted because Haskell98 implicitly uses all lowercase symbols in type-level expressions as type variables. Type variables are kind of like implicit parameters to a function: the caller gets to choose what particular type will be used, though they'll have to obey the...
Cᴏɴꜱᴛʀᴀɪɴᴛ(a, b, …). This is most often either
a type class identifier together with some of the type variables (e.g. Integral a) which means "the caller has to make sure we can use a as some kind of integral number – add other numbers to it etc.",
a tuple of such type class constraints, e.g. (Eq a, Show a), which basically means constraint-level and: all of the constraint need to be fulfilled, the caller needs to make sure the variables are members of all the required type classes.
Sɪɢɴᴀᴛᴜʀᴇ(a, b, …) is often some sort of function expression where the type variables may turn up on either side of an arrow. There can also be fixed types: much like you can mix literals and variables in (value-level) Haskell code, you can mix built-in types with local type variables. For example,
showInParens :: Show a => a -> String
showInParens x = "(" ++ show x ++ ")"
These are by far not the most general forms, though. In terms of modern Haskell,
Cᴏɴꜱᴛʀᴀɪɴᴛ(a, b, …) is any type-level expression of kind Constraint, wherein the type variables may turn up, but also any suitable type constructors.
Sɪɢɴᴀᴛᴜʀᴇ(a, b, …) is, quite similarly, any type-level expression of kind * (the kind of actual types), wherein the type variables may turn up, but also any suitable type constructors.
Now what is a type constructor? It's a lot like what values and functions are on the value level, but obviously on the type level. For instance,
GHCi> :k MaybeMaybe :: * -> *
which basically means: Maybe acts as a type-level function. It has the kind of a function which takes a type (*) and spits out another one (*), so, since Int is a type, Maybe Int is also a type.
This is a very general concept, and though it may take some time to fully grasp it I think the following explains quite well everything that might still need to be said:
GHCi> :k (->)
(->) :: * -> * -> *
GHCi> :k (,)
(,) :: * -> * -> *
GHCi> :k Eq
Eq :: * -> Constraint

Resources