Inference of if ... then ... else strange behaviour - haskell

Considering the following bad code :
fun x =
if (null x) then 0
else (take 50 x) : (fun (drop 50 x))
I noticed, I can load it into ghci without any problem, and that's the problem.
The program only retrieve me an error when i try to evaluate this function.
Regarding the default inference rule of if ... then ... else expression, as the two branches explicitly retrieve different type, why this code can be load (ie compiled) ? I mean, why the compiler can't figured out this code is ill-formed ?
Note : Of course if i add the correct type annotation for this function, as expected it'll be rejected, but in my understanding it should be rejected too without the type annotation.

Overloaded numeric literals. Haskell numeric literals are instances of whatever Num classes are defined, based on the type context.
The inferred type explains it:
Prelude> let f x = if null x then 0 else take 50 x : f (drop 50 x)
Prelude> :t f
f :: Num [[a]] => [a] -> [[a]]
That reads as "if you have an instance of the Num class for lists of lists of a, then this function takes a list of a to a list of list of a.
So it relies on a mythical instance of Num for lists of lists. If you tried to compile code that used this, without providing an instance of numbers for lists of lists, it would be a compilation error.
This example also illustrates why it is a good idea to write down the type signature first.

Let's check this out.
Prelude> let fun x = if (null x) then 0 else (take 50 x) : (fun (drop 50 x))
Prelude> :t fun
fun :: Num [[a]] => [a] -> [[a]]
As you can see the compiler infers a Num class for your result type.

Related

Getting all function arguments in haskel as list

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.

Insufficient definition of replicate

I have a question that I think is rather tricky.
The standard prelude contains the function
replicate :: Int -> a -> [a]
The following might seem like a reasonable definition for it
replicate n x = take n [x,x,..]
But it is actually not sufficient. Why not?
I know that the replicate function is defined as:
replicate :: Int -> a -> [a]
replicate n x = take n (repeat x)
And repeat is defined as:
repeat :: a -> [a]
repeat x = xs where xs = x:xs
Is the definition insufficient (from the question) because it uses an infinite list?
First of all there is a small syntax error in the question, it should be:
replicate n x = take n [x,x..]
-- ^ no comma
but let's not be picky.
Now when you use range syntax (i.e. x..), then x should be of a type that is an instance of Enum. Indeed:
Prelude> :t \n x -> take n [x,x..]
\n x -> take n [x,x..] :: Enum a => Int -> a -> [a]
You can argue that x,x.. will only generate x, but the Haskell compiler does not know that at compile time.
So the type in replicate (in the question) is too specific: it implies a type constraint - Enum a - that is actually not necessary.
Your own definition on the other hand is perfectly fine. Haskell has no problem with infinite lists since it uses lazy evaluation. Furthermore because you define xs with xs as tail, you actually constructed a circular linked list which also is better in terms of memory usage.

No instance for (Integral [t0]) error in Haskell code

I'm getting an error:
No instance for (Integral [t0]) when I run this haskell code.
boomBangs xs = [(a,b,c) |a<-[1..xs],b<-[1..xs],c<-[1..xs], xs <- xs `div` 2]
Where am I going wrong?
The problem is that you're trying to divide a list. In particular, xs `div` 2 is the incorrect expression.
You can get this from the error message: it's complaining that [t0] does not behave like an integer (e.g. it isn't in the Integral class). [t0] is just a list of stuff--the t0, being in lowercase, is a type variable that represntes any type.
Since lists of stuff aren't numbers, we can't really know how to divide them.
You can see why you get this exact error message by looking at the type of div:
div :: Integral i => i -> i -> i
All this means is that given some type i in the Integral class, you can divide two of them together to get a third. Since lists of things are not part of the integral class, you can't divide them and so you get an error.
If div had a concrete type like div :: Int -> Int -> Int, you would get an error telling you that it can't match the expected type Int with the actual type [t0]. However, since the type actually contains a variable i, the error is a bit more complex: [t0] cannot be a valid type to use in place of i because it is not in the Integral class.
What you said was:
Give me a tuple of a, b, and c:
[ (a, b, c)
For each a, b, and c in the list of values from 1 to xs1:
| a <- [1..xs1]
, b <- [1..xs1]
, c <- [1..xs1]
For each xs2 in the quotient of xs1 and 2.
, xs2 <- xs1 `div` 2
]
If you compile with warnings enabled (-Wall) or turn them on in GHCi (:set -Wall) then you’ll get a warning that the xs in xs <- ... shadows the xs in boomBangs xs = ..., and also that it’s unused. Obviously this kind of warning can be very helpful, as it points right to your problem.
Since xs1 is the input to your function, you end up with a type like this:
(Integral [t]) => [t] -> [([t], [t], [t])]
Which is to say that the function takes a list (xs1) that can act as a number ((`div` 2)) and gives you back a list of tuples of such lists. Even though you’re trying to divide a list by a number, GHC allows it and infers a more general type because you could have defined an Integral instance for lists. It only discovers that you haven’t when you actually try to use the function on a concrete type. Writing down type signatures can help keep the compiler grounded and give you better error messages.
I can only guess you meant for boomBangs to have a type like:
Integral t => [t] -> [(t, t, t)]
Or just:
[Int] -> [(Int, Int, Int)]
In which case maybe you were thinking of something like this:
[ (a, b, c)
| x <- xs
, a <- [1..x `div` 2]
, b <- [1..x `div` 2]
, c <- [1..x `div` 2]
]

Haskell type dessignation

I have to dessignate types of 2 functions(without using compiler :t) i just dont know how soudl i read these functions to make correct steps.
f x = map -1 x
f x = map (-1) x
Well i'm a bit confuse how it will be parsed
Function application, or "the empty space operator" has higher precedence than any operator symbol, so the first line parses as f x = map - (1 x), which will most likely1 be a type error.
The other example is parenthesized the way it looks, but note that (-1) desugars as negate 1. This is an exception from the normal rule, where operator sections like (+1) desugar as (\x -> x + 1), so this will also likely1 be a type error since map expects a function, not a number, as its first argument.
1 I say likely because it is technically possible to provide Num instances for functions which may allow this to type check.
For questions like this, the definitive answer is to check the Haskell Report. The relevant syntax hasn't changed from Haskell 98.
In particular, check the section on "Expressions". That should explain how expressions are parsed, operator precedence, and the like.
These functions do not have types, because they do not type check (you will get ridiculous type class constraints). To figure out why, you need to know that (-1) has type Num n => n, and you need to read up on how a - is interpreted with or without parens before it.
The following function is the "correct" version of your function:
f x = map (subtract 1) x
You should be able to figure out the type of this function, if I say that:
subtract 1 :: Num n => n -> n
map :: (a -> b) -> [a] -> [b]
well i did it by my self :P
(map) - (1 x)
(-)::Num a => a->a->->a
1::Num b=> b
x::e
map::(c->d)->[c]->[d]
map::a
a\(c->d)->[c]->[d]
(1 x)::a
1::e->a
f::(Num ((c->d)->[c]->[d]),Num (e->(c->d)->[c]->[d])) => e->(c->d)->[c]->[d]

user defined higher order functions in haskell

i went though several Haskell learning examples but i could not figure out how to write user defined higher order functions in Haskell
if we are taking a parameter as a function how the type of the function id defined?
Let's use the function map as a simple example. map takes a function and a list and applies the function to all elements of the list. If you write the signature of map, it runs like this:
First, you need a function. Any function is OK, so the type of the first argument is a -> b. Then, you need a list of input values. Since the type of the list's elements must fit to the function's input, the type of the list is [a]. For the output: What is the result of a function a -> b when applied to a value of type a? Right, it is b. So the result type is [b]. Assembled together, the type of our function runs like this:
map :: (a -> b) -> [a] -> [b]
And is defined like this:
map f [] = []
map f (x:xs) = f x : map f xs
Does this help you to understand the concept of high order functions?
Don't concern yourself with types just yet. Ask the compiler, it will tell you the types. With some practice you will be able to see the types almost as well as the compiler [grin].
Here we define two very simple higher-order functions, twice and compose. The first one takes a function and an argument, and applies one to the other, twice. The second one takes two functions and an argument and applies both functions to it in chain.
$ ghci
GHCi, version 6.12.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> let twice f x = f (f x)
Prelude> :t twice
twice :: (t -> t) -> t -> t
Prelude> let compose f g x = f (g x)
Prelude> :t compose
compose :: (t1 -> t2) -> (t -> t1) -> t -> t2
Prelude>
You can see that twice gets two arguments, of type (t->t) an of type t, and returns a resulkt of type t. t is any type (but the same in all 4 occurrences).
You can try to use these higher-order functions on some regular functions.
Prelude> let times3 x = x * 3
Prelude> let times5 x = x * 5
Prelude> twice times3 2
18
Prelude> twice times5 2
50
Prelude> compose times3 times5 2
30
Prelude>
Ans some funky advanced stuff:
Prelude> (twice twice) times3 2
162
Prelude> twice (twice times3) 2
162
Prelude>
Do you understand what's going on in the last two examples?

Resources