I have not seen a convincing use case for multivarian functions in haskell, but so far this has not been solved using a list or a similar data structure. Therefore, if you think that you have one beyond the limits of novelty, the reason I played with them, I would be interested to know what it is. There are enough examples below, some of which I should have thought when writing the comment, that I canceled my expression.
{-
Then after uploading the file to ghci:
> mySum 1 2 4 5 6 7 :: Int 25 > mySum 1.1 2 4.6 5 6.9 7 :: Double 26.6
Type inference can also be your friend in some cases, allowing you to discard the final type annotation, as in the following far-fetched case:
> replicate (mySum 1 2 3 4) 6 [6,6,6,6,6,6,6,6,6,6]
Regarding
Also, is there an equivalent function above that doesn't rely on extensions?
I think you're out of luck. I would like to point out that if you have no reason to leave the GHC or stay with Haskell98 or Haskell2010, you will not harm you or cause compatibility problems, as most people seem to be in GHC anyway.
Edit: additional explanation
Let's start by explaining the difference between simpler instances. I will add postfix 2 to some of the implementation names that I have provided.
instance (Num n) => MySumType nn where mySum x = x
If you combine this with a class declaration:
class (Num n) => MySumType nr where mySum :: n -> r
mySum has a signature like mySum :: (Num n) => n -> n . That n -> n says function 1 arity, which takes type n , creates n and n has class Num.
When using this mySum I must indicate what I give it and what it produces.
mySum 1 :: Int mySum (1 :: Int)
both will give errors only when specifying the type of input and output, will it give the result:
mySum (1 :: Int) :: Int ^ ^ | specify output type specify input type
gives the result (1 in this case). This is because you provided an instance for n -> n , but you can add an instance for n -> m later, for example Int -> Double , as shown below:
instance MySumType Int Double where mySum x = 2 * fromIntegral x > mySum (1::Int) :: Int 1 > mySum (1::Int) :: Double 2.0
All of these instances correspond to a very narrow range of all possible types of arity functions.
Now consider the modified version
instance (Num n, m~n) => MySumType nm where mySum x = x
mySum here has a signature of type mySum :: (Num n, m~n) => n -> m signature of this type for all 1 arity functions that take type n and produce type m , where n has class Num and m is equal to n . Note that this started by matching all 1 functions with arity, n -> m , any n for any m , and then placing contests on it.
Now you can do:
> mySum2 (1::Int) 1 > mySum2 1 :: Int 1
Once input is specified, the output is also indicated. Other explanations 1 , 2 .
This does not stop us from specific, more specific instances, such as Int -> Double , as before:
instance MySumType Int Double where mySum x = 2 * fromIntegral x > mySum2 1 :: Int 1 > mySum2 1 :: Double 1.0 > mySum2 (1 :: Int) :: Double 2.0
Only the last mySum2 disables the Int -> Double instance. This is an IncoherentInstances property, and I think I will leave it with another stackoverflow question to answer the role that IncoherentInstances plays.