I want to be able to compose numeric functions in haskell using binary operators. So, for example, with unary numeric functions:
f*g
should translate to:
\x -> (f x)*(g x)
and similarly for addition. Making your own operator to do this is pretty straightforward, but I'd really like to just make Num a => a -> a functions an instance of Num, but I'm not sure how to do so.
I'd also like to make this arity generic, but that might be too much trouble for how difficult it is to do arity generic functions in Haskell, so it might just be better to define seperate Num a => a -> a -> a, Num a => a -> a -> a -> a, etc... instances up to some reasonably large number.
The idiomatic approach
There is an instance of Applicative for (->) a, which means that all functions are applicative functors. The modern idiom for composing any functions in the way you're describing is to use Applicative, like this:
(*) <$> f <*> g
liftA2 (*) f g -- these two are equivalent
This makes the operation clear. Both of these approaches are slightly more verbose but seem to me to express the combination pattern far more clearly.
Furthermore, this is a far more general approach. If you understand this idiom, you will be able to apply it in many other contexts than just Num. If you're not familiar with Applicative, one place to start is the Typeclassopedia. If you're theoretically inclined, you may check McBride and Patterson's famous article. (For the record, I'm using "idiom" here in the ordinary sense, but mindful of the pun.)
Num b => Num (a -> b)
The instance you want (and others besides) is available in the NumInstances package. You can copy out the instance #genisage posted; they're functionally identical. (#genisage wrote it out more explicitly; comparing the two implementations may be enlightening.) Importing the library on Hackage has the benefit of highlighting for other developers that you're using an orphan instance.
There's a problem with Num b => Num (a -> b), however. In short, 2 is now not only a number but also a function with an infinite number of arguments, all of which it ignores. 2 (3 + 4) now equals 2. Any use of an integer literal as a function will almost certainly give an unexpected and incorrect result, and there's no way to warn the programmer short of a runtime exception.
As spelled out in the 2010 Haskell Report section 6.4.1, "An integer literal represents the application of the function fromInteger to the appropriate value of type Integer." This means writing 2 or 12345 in your source code or in GHCi is equivalent to writing fromInteger 2 or fromInteger 12345. Either expression therefore has type Num a => a.
As a result, fromInteger is absolutely pervasive in Haskell. Normally this works out wonderfully; when you write a number in your source code, you get a number--of the appropriate type. But with your Num instance for functions, the type of fromInteger 2 could very well be a -> Integer or a -> b -> Integer. In fact, GHC will happily replace the literal 2 with a function, not a number--and a particularly dangerous function too, one that discards any data given to it. (fromInteger n = \_ -> n or const n; i.e. throw out all arguments and just give n.)
Often you can get away with not implementing inapplicable class members, or by implementing them with undefined, either of which gives a runtime error. This is, for the same reasons, not a fix to the present problem.
A more sensible instance: pseudo-Num a => Num (a -> a)
If you're willing to restrict yourself to multiplying and adding unary functions of type Num a => a -> a, we can ameliorate the fromInteger problem a bit, or at least have 2 (3 + 5) equal 16 rather than 2. The answer is simply to define fromInteger 3 as (*) 3 rather than const 3:
instance (a ~ b, Num a) => Num (a -> b) where
fromInteger = (*) . fromInteger
negate = fmap negate
(+) = liftA2 (+)
(*) = liftA2 (*)
abs = fmap abs
signum = fmap signum
ghci> 2 (3 + 4)
14
ghci> let x = 2 ((2 *) + (3 *))
ghci> :t x
x :: Num a => a -> a
ghci> x 1
10
ghci> x 2
40
Note that although this is perhaps morally equivalent to Num a => Num (a -> a), it has to be defined with the equality constraint (which requires GADTs or TypeFamilies). Otherwise we'll get an ambiguity error for something like (2 3) :: Int. I'm not up to explaining why, sorry. Basically, the equality constraint a ~ b => a -> b allows the inferred or stated type of b to propagate to a during inference.
For a nice explanation of why and how this instance works, see the answer to Numbers as multiplicative functions (weird but entertaining).
Orphan instance warning
Do not expose any module that contains--or imports a module that contains--or imports a module that imports a module that contains...--either of these instances without understanding the problem of orphan instances and/or warning your users accordingly.
an instance with generic arity
instance Num b => Num (a->b) where
f + g = \x -> f x + g x
f - g = \x -> f x - g x
f * g = \x -> f x * g x
negate f = negate . f
abs f = abs . f
signum f = signum . f
fromInteger n = \x -> fromInteger n
Edit: As Christian Conkle points out, there are problems with this approach. If you plan to use these instances for anything important or just want to understand the issues, you should read the resources he provided and decide for yourself whether this fits your needs. My intention was to provide an easy way to play with numeric functions using natural notation with as simple an implementation as possible.
Related
Is there a way in haskell to get all function arguments as a list.
Let's supose we have the following program, where we want to add the two smaller numbers and then subtract the largest. Suppose, we can't change the function definition of foo :: Int -> Int -> Int -> Int. Is there a way to get all function arguments as a list, other than constructing a new list and add all arguments as an element of said list? More importantly, is there a general way of doing this independent of the number of arguments?
Example:
module Foo where
import Data.List
foo :: Int -> Int -> Int -> Int
foo a b c = result!!0 + result!!1 - result!!2 where result = sort ([a, b, c])
is there a general way of doing this independent of the number of arguments?
Not really; at least it's not worth it. First off, this entire idea isn't very useful because lists are homogeneous: all elements must have the same type, so it only works for the rather unusual special case of functions which only take arguments of a single type.
Even then, the problem is that “number of arguments” isn't really a sensible concept in Haskell, because as Willem Van Onsem commented, all functions really only have one argument (further arguments are actually only given to the result of the first application, which has again function type).
That said, at least for a single argument- and final-result type, it is quite easy to pack any number of arguments into a list:
{-# LANGUAGE FlexibleInstances #-}
class UsingList f where
usingList :: ([Int] -> Int) -> f
instance UsingList Int where
usingList f = f []
instance UsingList r => UsingList (Int -> r) where
usingList f a = usingList (f . (a:))
foo :: Int -> Int -> Int -> Int
foo = usingList $ (\[α,β,γ] -> α + β - γ) . sort
It's also possible to make this work for any type of the arguments, using type families or a multi-param type class. What's not so simple though is to write it once and for all with variable type of the final result. The reason being, that would also have to handle a function as the type of final result. But then, that could also be intepreted as “we still need to add one more argument to the list”!
With all respect, I would disagree with #leftaroundabout's answer above. Something being
unusual is not a reason to shun it as unworthy.
It is correct that you would not be able to define a polymorphic variadic list constructor
without type annotations. However, we're not usually dealing with Haskell 98, where type
annotations were never required. With Dependent Haskell just around the corner, some
familiarity with non-trivial type annotations is becoming vital.
So, let's take a shot at this, disregarding worthiness considerations.
One way to define a function that does not seem to admit a single type is to make it a method of a
suitably constructed class. Many a trick involving type classes were devised by cunning
Haskellers, starting at least as early as 15 years ago. Even if we don't understand their
type wizardry in all its depth, we may still try our hand with a similar approach.
Let us first try to obtain a method for summing any number of Integers. That means repeatedly
applying a function like (+), with a uniform type such as a -> a -> a. Here's one way to do
it:
class Eval a where
eval :: Integer -> a
instance (Eval a) => Eval (Integer -> a) where
eval i = \y -> eval (i + y)
instance Eval Integer where
eval i = i
And this is the extract from repl:
λ eval 1 2 3 :: Integer
6
Notice that we can't do without explicit type annotation, because the very idea of our approach is
that an expression eval x1 ... xn may either be a function that waits for yet another argument,
or a final value.
One generalization now is to actually make a list of values. The science tells us that
we may derive any monoid from a list. Indeed, insofar as sum is a monoid, we may turn arguments to
a list, then sum it and obtain the same result as above.
Here's how we can go about turning arguments of our method to a list:
class Eval a where
eval2 :: [Integer] -> Integer -> a
instance (Eval a) => Eval (Integer -> a) where
eval2 is i = \j -> eval2 (i:is) j
instance Eval [Integer] where
eval2 is i = i:is
This is how it would work:
λ eval2 [] 1 2 3 4 5 :: [Integer]
[5,4,3,2,1]
Unfortunately, we have to make eval binary, rather than unary, because it now has to compose two
different things: a (possibly empty) list of values and the next value to put in. Notice how it's
similar to the usual foldr:
λ foldr (:) [] [1,2,3,4,5]
[1,2,3,4,5]
The next generalization we'd like to have is allowing arbitrary types inside the list. It's a bit
tricky, as we have to make Eval a 2-parameter type class:
class Eval a i where
eval2 :: [i] -> i -> a
instance (Eval a i) => Eval (i -> a) i where
eval2 is i = \j -> eval2 (i:is) j
instance Eval [i] i where
eval2 is i = i:is
It works as the previous with Integers, but it can also carry any other type, even a function:
(I'm sorry for the messy example. I had to show a function somehow.)
λ ($ 10) <$> (eval2 [] (+1) (subtract 2) (*3) (^4) :: [Integer -> Integer])
[10000,30,8,11]
So far so good: we can convert any number of arguments into a list. However, it will be hard to
compose this function with the one that would do useful work with the resulting list, because
composition only admits unary functions − with some trickery, binary ones, but in no way the
variadic. Seems like we'll have to define our own way to compose functions. That's how I see it:
class Ap a i r where
apply :: ([i] -> r) -> [i] -> i -> a
apply', ($...) :: ([i] -> r) -> i -> a
($...) = apply'
instance Ap a i r => Ap (i -> a) i r where
apply f xs x = \y -> apply f (x:xs) y
apply' f x = \y -> apply f [x] y
instance Ap r i r where
apply f xs x = f $ x:xs
apply' f x = f [x]
Now we can write our desired function as an application of a list-admitting function to any number
of arguments:
foo' :: (Num r, Ord r, Ap a r r) => r -> a
foo' = (g $...)
where f = (\result -> (result !! 0) + (result !! 1) - (result !! 2))
g = f . sort
You'll still have to type annotate it at every call site, like this:
λ foo' 4 5 10 :: Integer
-1
− But so far, that's the best I can do.
The more I study Haskell, the more I am certain that nothing is impossible.
So, I'm trying to write my own replacement for Prelude, and I have (^) implemented as such:
{-# LANGUAGE RebindableSyntax #-}
class Semigroup s where
infixl 7 *
(*) :: s -> s -> s
class (Semigroup m) => Monoid m where
one :: m
class (Ring a) => Numeric a where
fromIntegral :: (Integral i) => i -> a
fromFloating :: (Floating f) => f -> a
class (EuclideanDomain i, Numeric i, Enum i, Ord i) => Integral i where
toInteger :: i -> Integer
quot :: i -> i -> i
quot a b = let (q,r) = (quotRem a b) in q
rem :: i -> i -> i
rem a b = let (q,r) = (quotRem a b) in r
quotRem :: i -> i -> (i, i)
quotRem a b = let q = quot a b; r = rem a b in (q, r)
-- . . .
infixr 8 ^
(^) :: (Monoid m, Integral i) => m -> i -> m
(^) x i
| i == 0 = one
| True = let (d, m) = (divMod i 2)
rec = (x*x) ^ d in
if m == one then x*rec else rec
(Note that the Integral used here is one I defined, not the one in Prelude, although it is similar. Also, one is a polymorphic constant that's the identity under the monoidal operation.)
Numeric types are monoids, so I can try to do, say 2^3, but then the typechecker gives me:
*AlgebraicPrelude> 2^3
<interactive>:16:1: error:
* Could not deduce (Integral i0) arising from a use of `^'
from the context: Numeric m
bound by the inferred type of it :: Numeric m => m
at <interactive>:16:1-3
The type variable `i0' is ambiguous
These potential instances exist:
instance Integral Integer -- Defined at Numbers.hs:190:10
instance Integral Int -- Defined at Numbers.hs:207:10
* In the expression: 2 ^ 3
In an equation for `it': it = 2 ^ 3
<interactive>:16:3: error:
* Could not deduce (Numeric i0) arising from the literal `3'
from the context: Numeric m
bound by the inferred type of it :: Numeric m => m
at <interactive>:16:1-3
The type variable `i0' is ambiguous
These potential instances exist:
instance Numeric Integer -- Defined at Numbers.hs:294:10
instance Numeric Complex -- Defined at Numbers.hs:110:10
instance Numeric Rational -- Defined at Numbers.hs:306:10
...plus four others
(use -fprint-potential-instances to see them all)
* In the second argument of `(^)', namely `3'
In the expression: 2 ^ 3
In an equation for `it': it = 2 ^ 3
I get that this arises because Int and Integer are both Integral types, but then why is it that in normal Prelude I can do this just fine? :
Prelude> :t (2^)
(2^) :: (Num a, Integral b) => b -> a
Prelude> :t 3
3 :: Num p => p
Prelude> 2^3
8
Even though the signatures for partial application in mine look identical?
*AlgebraicPrelude> :t (2^)
(2^) :: (Numeric m, Integral i) => i -> m
*AlgebraicPrelude> :t 3
3 :: Numeric a => a
How would I make it so that 2^3 would in fact work, and thus give 8?
A Hindley-Milner type system doesn't really like having to default anything. In such a system, you want types to be either properly fixed (rigid, skolem) or properly polymorphic, but the concept of “this is, like, an integer... but if you prefer, I can also cast it to something else” as many other languages have doesn't really work out.
Consequently, Haskell sucks at defaulting. It doesn't have first-class support for that, only a pretty hacky ad-hoc, hard-coded mechanism which mainly deals with built-in number types, but fails at anything more involved.
You therefore should try to not rely on defaulting. My opinion is that the standard signature for ^ is unreasonable; a better signature would be
(^) :: Num a => a -> Int -> a
The Int is probably controversial – of course Integer would be safer in a sense; however, an exponent too big to fit in Int generally means the results will be totally off the scale anyway and couldn't feasibly be calculated by iterated multiplication; so this kind of expresses the intend pretty well. And it gives best performance for the extremely common situation where you just write x^2 or similar, which is something where you very definitely don't want to have to put an extra signature in the exponent.
In the rather fewer cases where you have a concrete e.g. Integer number and want to use it in the exponent, you can always shove in an explicit fromIntegral. That's not nice, but rather less of an inconvenience.
As a general rule, I try to avoid† any function-arguments that are more polymorphic than the results. Haskell's polymorphism works best “backwards”, i.e. the opposite way as in dynamic language: the caller requests what type the result should be, and the compiler figures out from this what the arguments should be. This works pretty much always, because as soon as the result is somehow used in the main program, the types in the whole computation have to be linked to a tree structure.
OTOH, inferring the type of the result is often problematic: arguments may be optional, may themselves be linked only to the result, or given as polymorphic constants like Haskell number literals. So, if i doesn't turn up in the result of ^, avoid letting in occur in the arguments either.
†“Avoid” doesn't mean I don't ever write them, I just don't do so unless there's a good reason.
I've discovered these kinds of type signatures:
x :: a b -> Int
x f = 3
y :: a b c -> Int
y f = 3
z :: a b c d -> Int
z f = 3
> x [1] -- 3
> y (1, 2) -- 3
> z (1, 2, 3) -- 3
Basically:
x only accepts a value inhabiting a type constructor with 1 parameter or more.
y only accepts a value inhabiting a type constructor with 2 parameters or more.
z only accepts a value inhabiting a type constructor with 3 parameters or more.
They are valid, but I'm not sure what they mean nor what they could be used for.
They seem related to polytypic notions or polymorphism over type constructors, but enforce an invariant based on many parameters the type constructor accepts.
Without further constraints, such types are useless – there's nothing you could really do with them, expect pass them right on. But that's actually the same situation with a signature a -> Int: if nothing is known about a, there's nothing you can do with it either!
However, like with e.g. toInteger :: Integral a => a -> Integer, adding constraints to the arguments allows you to do stuff. For instance,
import Data.Foldable
import Prelude hiding (foldr)
x' :: (Foldable a, Integral b) => a b -> Integer
x' = foldr ((+) . toInteger) 0
Rather more often than not, when you have a type of the form a b ... n o p q, then a b ... p is at least an instance of the Functor class, often also Applicative and Monad; sometimes Foldable, Traversable, or Comonad; sometimes a b ... o will be Arrow... These constraints allow you to do quite a lot with the composite types, without knowing what particular type constructors you're dealing with.
After studying #leftaroundabout answer and experimenting in GHCI, I've come to an understanding with composite types. Their unification with applied types is based on both the evaluation order and their type variable's kind signature. The evaluation order is quite important as a b c ~ (((a) b) c) while a (b c) is (a ((b) c). This makes a b c match composite types where a is matched with type constructors of kind * -> * -> *, and a b with * -> * and a b c with *.
I explained it fully with diagrams and GHCI code in this gist (https://gist.github.com/CMCDragonkai/2a1d3ecb67dcdabfc7e0) (it's too long for stack overflow)
While I've seen all kinds of weird things in Haskell sample code - I've never seen an operator plus being overloaded. Is there something special about it?
Let's say I have a type like Pair, and I want to have something like
Pair(2,4) + Pair(1,2) = Pair(3,6)
Can one do it in haskell?
I am just curious, as I know it's possible in Scala in a rather elegant way.
Yes
(+) is part of the Num typeclass, and everyone seems to feel you can't define (*) etc for your type, but I strongly disagree.
newtype Pair a b = Pair (a,b) deriving (Eq,Show)
I think Pair a b would be nicer, or we could even just use the type (a,b) directly, but...
This is very much like the cartesian product of two Monoids, groups, rings or whatever in maths, and there's a standard way of defining a numeric structure on it, which would be sensible to use.
instance (Num a,Num b) => Num (Pair a b) where
Pair (a,b) + Pair (c,d) = Pair (a+c,b+d)
Pair (a,b) * Pair (c,d) = Pair (a*c,b*d)
Pair (a,b) - Pair (c,d) = Pair (a-c,b-d)
abs (Pair (a,b)) = Pair (abs a, abs b)
signum (Pair (a,b)) = Pair (signum a, signum b)
fromInteger i = Pair (fromInteger i, fromInteger i)
Now we've overloaded (+) in an obvious way, but also gone the whole hog and overloaded (*) and all the other Num functions in the same, obvious, familiar way mathematics does it for a pair. I just don't see the problem with this. In fact I think it's good practice.
*Main> Pair (3,4.0) + Pair (7, 10.5)
Pair (10,14.5)
*Main> Pair (3,4.0) + 1 -- *
Pair (4,5.0)
* - Notice that fromInteger is applied to numeric literals like 1, so this was interpreted in that context as Pair (1,1.0) :: Pair Integer Double. This is also quite nice and handy.
Overloading in Haskell is only available using type classes. In this case, (+) belongs to the Num type class, so you would have to provide a Num instance for your type.
However, Num also contains other functions, and a well-behaved instance should implement all of them in a consistent way, which in general will not make sense unless your type represents some kind of number.
So unless that is the case, I would recommend defining a new operator instead. For example,
data Pair a b = Pair a b
deriving Show
infixl 6 |+| -- optional; set same precedence and associativity as +
Pair a b |+| Pair c d = Pair (a+c) (b+d)
You can then use it like any other operator:
> Pair 2 4 |+| Pair 1 2
Pair 3 6
I'll try to come at this question very directly, since you are keen on getting a straight "yes or no" on overloading (+). The answer is yes, you can overload it. There are two ways to overload it directly, without any other changes, and one way to overload it "correctly" which requires creating an instance of Num for your datatype. The correct way is elaborated on in the other answers, so I won't go over it.
Edit: Note that I'm not recommending the way discussed below, just documenting it. You should implement the Num typeclass and not anything I write here.
The first (and most "wrong") way to overload (+) is to simply hide the Prelude.+ function, and define your own function named (+) that operates on your datatype.
import Prelude hiding ((+)) -- hide the autoimport of +
import qualified Prelude as P -- allow us to refer to Prelude functions with a P prefix
data Pair a = Pair (a,a)
(+) :: Num a => Pair a -> Pair a -> Pair a -- redefinition of (+)
(Pair (a,b)) + (Pair (c,d)) = Pair ((P.+) a c,(P.+) b d ) -- using qualified (+) from Prelude
You can see here, we have to go through some contortions to hide the regular definition of (+) from being imported, but we still need a way to refer to it, since it's the only way to do fast machine addition (it's a primitive operation).
The second (slightly less wrong) way to do it is to define your own typeclass that only includes a new operator you name (+). You'll still have to hide the old (+) so haskell doesn't get confused.
import Prelude hiding ((+))
import qualified Prelude as P
data Pair a = Pair (a,a)
class Addable a where
(+) :: a -> a -> a
instance Num a => Addable (Pair a) where
(Pair (a,b)) + (Pair (c,d)) = Pair ((P.+) a c,(P.+) b d )
This is a bit better than the first option because it allows you to use your new (+) for lots of different data types in your code.
But neither of these are recommended, because as you can see, it is very inconvenient to access the regular (+) operator that is defined in the Num typeclass. Even though haskell allows you to redefine (+), all of the Prelude and the libraries are expecting the original (+) definition. Lucky for you, (+) is defined in a typeclass, so you can just make Pair an instance of Num. This is probably the best option, and it is what the other answerers have recommended.
The issue you are running into is that there are possibly too many functions defined in the Num typeclass (+ is one of them). This is just a historical accident, and now the use of Num is so widespread, it would be hard to change it now. Instead of splitting those functionalities out into separate typeclasses for each function (so they can be overridden separately) they are all glommed together. Ideally the Prelude would have an Addable typeclass, and a Subtractable typeclass etc. that allow you to define an instance for one operator at a time without having to implement everything that Num has in it.
Be that as it may, the fact is that you will be fighting an uphill battle if you want to write a new (+) just for your Pair data type. Too much of the other Haskell code depends on the Num typeclass and its current definition.
You might look into the Numeric Prelude if you are looking for a blue-sky reimplementation of the Prelude that tries to avoid some of the mistakes of the current one. You'll notice they've reimplemented the Prelude just as a library, no compiler hacking was necessary, though it's a huge undertaking.
Overloading in Haskell is made possible through type classes. For a good overview, you might want to look at this section in Learn You a Haskell.
The (+) operator is part of the Num type class from the Prelude:
class (Eq a, Show a) => Num a where
(+), (*), (-) :: a -> a -> a
negate :: a -> a
...
So if you'd like a definition for + to work for pairs, you would have to provide an instance.
If you have a type:
data Pair a = Pair (a, a) deriving (Show, Eq)
Then you might have a definition like:
instance Num a => Num (Pair a) where
Pair (x, y) + Pair (u, v) = Pair (x+u, y+v)
...
Punching this into ghci gives us:
*Main> Pair (1, 2) + Pair (3, 4)
Pair (4,6)
However, if you're going to give an instance for +, you should also be providing an instance for all of the other functions in that type class too, which might not always make sense.
If you only want (+) operator rather than all the Num operators, probably you have a Monoid instance, for example Monoid instance of pair is like this:
class (Monoid a, Monoid b) => Monoid (a, b) where
mempty = (mempty, mempty)
(a1, b1) `mappend` (a2, b2) = (a1 `mappend` a2, b1 `mappend` b2)
You can make (++) a alias of mappend, then you can write code like this:
(1,2) ++ (3,4) == (4,6)
("hel", "wor") ++ ("lo", "ld") == ("hello", "world")
I want to take some of the boilerplate out of Num declarations for a few custom classes (call them Monomial and Polynomial). Instead of writing
instance Num (Monomial) where
f - g = f + (negate g)
abs _ = undefined
Is there a way to get around this? I came across default superclass instances and something called "the strathclyde haskell enhancement" which if implemented might let me write something like,
class SimpleNum a => Num a where
(+) :: a -> a -> a -- standard ring stuff
(*) :: a -> a -> a
one :: a
zero :: a
instance Num (SimpleNum a) where
f - g = f + (negate g)
abs _ = undefined
What's the usual / simple way of dealing with this?
The usual ways of dealing this is to do at least one or more of the following:
Grumble a lot.
Write helper functions like this:
simpleMinus f g = f + (negate g)
Use tools like Template Haskell and Derive.
Attempt to implement extensions like the one you mention. (This unfortunately not as easy as you might think.)