I've just started to learn Haskell after coming from Python, and I've got a couple of questions about functions. I've written the following code:
--generating prime list
primes = sieve [2..]
sieve (p:ps) = p : sieve [x | x <- ps, mod x p /= 0]
--factorising function
--takes an input of a number and a list of primes and outputs a list of its prime factors
factorise (n,ps)
| mod n head ps /= 0 = div n head ps : factorise (div n head ps, ps)
| otherwise = factorise (n,tail ps)
Firstly, when I try to compile, I get an error relating to n, saying I cannot construct the infinite type: a ~ [a] -> a, why is this?
Secondly, while I understand the logic behind creating an infinite list, why do you not have to explicitly state the types of the function sieve, are the types implied? Would I have to, for the factorise function?
Lastly, is there a more concise way of writing the above algorithm (which I understand is horribly efficient)?
Adding some parentheses here and there fixes the problem:
Parentheses are used for grouping in Haskell.
mod n (head ps)is an application ofmodto two arguments,nandhead ps; without the parensmod n head psis an application ofmodto three arguments,n,headand ps`, and this just doesn't typecheck.Indeed after the error is fixed all the types are successfully inferred, as
Now you can specialize them if you so wish, as
(the latter way of writing the type for
factoriseneeds theGADTsextension enabled).For your original code with the type signature included,
the error message is essentially the same. It says "Could not deduce
(a ~ ([a] -> a))" but still shows that as far as the compiler can see, theatype must also be[a] -> aat the same time (so it must also bea ~ [a] -> ([a] -> a),a ~ [[a] -> a] -> ([a] -> ([a] -> a)), etc. etc. (hence the "infinite" type reference in the first error message)).If that were indeed the type you intended it could be made legal by naming it and making it explicitly recursive, as
This is allowed. Haskell is perfectly capable of having recursive types. After all, simple list type is recursive, as if defined by
I'll leave addressing the efficiency issues in
factorisefor later. Withsievethough it is pretty straightforward: its main problem is that it only produces one prime at a time, whereas it is perfectly capable of producing more, much more than that, at each one step.Can you find a way how?
Your
factorisefunction is a perfectly fine rendering of the simple trial division factorization algorithm (except for few simple errors). One way to improve conciseness (and subsequently correctness!) is to introduce interim variables withlet(or, better,where, to be able to use them in guards as well), as in... except it never stops! You must include an additional test to stop producing the list of prime factors.
Can you find a way how? :)