I'm looking through a past exam paper and don't understand how to convert Int to [Int].
For example, one of the questions asks us to produce a list of all the factors of a whole number excluding both the number itself and 1.
strictFactors Int -> [Int]
strictFactors x = ???
I'm not asking for anyone to do this question for me! I just want to know how I'd convert an integer input to a list of integer output. Thanks!
Perhaps it would be easiest to have a look at some similar code. As requested, I won't give you the answer, but you should be able to use these ideas to do what you want.
Brute force
Here we're just going to use all the pairs of numbers between 1 and x to test if we can make x as the sum of two square numbers:
sumOfSquares :: Int -> [Int]
sumOfSquares x = [ (a,b) | a <- [1..x], b <- [a..x], a^2 + b^2 == x]
You call this like this:
ghci> asSumOfSquares 50
[(1,7),(5,5)]
because 50 = 1^2+7^2 and also 50 = 5^2 + 5^2.
You can think of sumOfSquares as working by first taking an a from the list [1..x] of numbers between 1 and x and then another between that and x. It then checks a^2 + b^2 == x. If that's True, it adds (a,b) to the resulting list.
Generate and check
This time let's generate some single numbers then check whether they're a multiple of another. This will calculate the least common multiple (lcm). For example, the least common multiple of 15 and 12 is 60, because it's the first number that's in both the 15 and 12 times tables.
This function isn't of the type you want but it uses all the techniques you want.
lcm :: Int -> Int -> Int
lcm x y = head [x*a | a <- [1..], (x*a) `mod` y == 0]
You can call that like this:
ghci> lcm 12 15
60
This time the list of numbers [1..] is (in principle) infinite; good job we're just picking the first one with head!
(x*a) `mod` y == 0 does the checking to see whether the number x*a is a multiple of y (mod gives the remainder after division). That's a key idea you should use.
Summary
Use a <- [1..end] to generate numbers, test them with a True/False expression (i.e. a Bool), perhaps using the mod function.
I'm quite new at Haskell but can think of a myriad ways of "converting" an Int to a list containing that same Int:
import Control.Applicative (pure)
sane_lst :: Int -> [Int]
sane_lst x = [x]
lst :: Int -> [Int]
lst x = take 1 $ repeat x
lst' :: Int -> [Int]
lst' = replicate 1
lst'' :: Int -> [Int]
lst'' = return
lst''' :: Int -> [Int]
lst''' = pure
lst'''' :: Int -> [Int]
lst'''' x = enumFromTo x x
I guess the point here is that you don't "convert" to a list, you rather "construct" the list you need. The staightforward strategy for the kind of question you posed is to find something that will give you a suitable starting list to work with based on your parameter, then filter, fold or comprehend as needed.
For example when I say:
lst x = take 1 $ repeat x
I'm first constructing an infinite list repeating the value I passed in, and then taking from it a list containing just the first element. So if you think about what kind of list you need to start with to find the solution to your problem you'll be halfway there.
If your only goal is to convert between the types (for now) then strictFactors x = [x] is the most canonical answer. This function is also called pure since [] is what's known as an Applicative and return since [] is known as a Monad.
Related
I want to add two positive numbers together without the use of any basic operators like + for addition. I've already worked my way around that (in the add''' function) (i think) may not be efficient but thats not the point right now. I am getting lots of type errors however which i have no idea how to handle, and is very confusing for me as it works on paper and i've come from python.
add 1245 7489
--add :: Int -> Int -> Int
add x y = add'' (zip (add' x) (add' y))
where
add' :: Int -> [Int]
add' 0 = []
add' x = add' (x `div` 10) ++ [x `mod` 10]
conversion [1,2,4,5] [7,4,8,9] then zipping them together [(1,7),(2,4)....]
add'' :: [(Int,Int)] -> [Int]
add'' (x:xs) = [(add''' (head x) (last x))] ++ add'' xs
summary [8,6,...] what happens when the sum reaches 10 is not implemented yet.
where
--add''' :: (Int,Int) -> Int
add''' x y = last (take (succ y) $ iterate succ x)
adding two numbers together
You can't use head and last on tuples. ...Frankly, you should never use these functions at all because they're unsafe (partial), but they can be used on lists. In Haskell, lists are something completely different from tuples.To get at the elements of a tuple, use pattern matching.
add'' ((x,y):xs) = [add''' x y] ++ add'' xs
(To get at the elements of a list, pattern matching is very often the best too.) Alternatively, you can use fst and snd, these do on 2-tuples what you apparently thought head and last would.
Be clear which functions are curried and which aren't. The way you write add''', its type signature is actually Int -> Int -> Int. That is equivalent to (Int, Int) -> Int, but it's still not the same to the type checker.
The result of add'' is [Int], but you're trying to use this as Int in the result of add. That can't work, you need to translate from digits to numbers again.
add'' doesn't handle the empty case. That's fixed easily enough, but better than doing this recursion at all is using standard combinators. In your case, this is only supposed to work element-wise anyway, so you can simply use map – or do that right in the zipping, with zipWith. Then you also don't need to unwrap any tuples at all, because it works with a curried function.
A clean version of your attempt:
add :: Int -> Int -> Int
add x y = fromDigits 0 $ zipWith addDigits (toDigits x []) (toDigits y [])
where
fromDigits :: Int -> [Int] -> Int
fromDigits acc [] = acc
fromDigits acc (d:ds)
= acc `seq` -- strict accumulator, to avoid thunking.
fromDigits (acc*10 + d) ds
toDigits :: Int -> [Int] -> [Int] -- yield difference-list,
toDigits 0 = id -- because we're consing
toDigits x = toDigits (x`div`10) . ((x`mod`10):) -- left-associatively.
addDigits :: Int -> Int -> Int
addDigits x y = last $ take (succ x) $ iterate succ y
Note that zipWith requires both numbers to have the same number of digits (as does zip).
Also, yes, I'm using + in fromDigits, making this whole thing pretty futile. In practice you would of course use binary, then it's just a bitwise-or and the multiplication is a left shift. What you actually don't need to do here is take special care with 10-overflow, but that's just because of the cheat of using + in fromDigits.
By head and last you meant fst and snd, but you don't need them at all, the components are right there:
add'' :: [(Int, Int)] -> [Int]
add'' (pair : pairs) = [(add''' pair)] ++ add'' pairs
where
add''' :: (Int, Int) -> Int
add''' (x, y) = last (take (succ y) $ iterate succ x)
= iterate succ x !! y
= [x ..] !! y -- nice idea for an exercise!
Now the big question that remains is what to do with those big scary 10-and-over numbers. Here's a thought: produce a digit and a carry with
= ([(d, 0) | d <- [x .. 9]] ++ [(d, 1) | d <- [0 ..]]) !! y
Can you take it from here? Hint: reverse order of digits is your friend!
the official answer my professor gave
works on positive and negative numbers too, but still requires the two numbers to be the same length
add 0 y = y
add x y
| x>0 = add (pred x) (succ y)
| otherwise = add (succ x) (pred y)
The other answers cover what's gone wrong in your approach. From a theoretical perspective, though, they each have some drawbacks: they either land you at [Int] and not Int, or they use (+) in the conversion back from [Int] to Int. What's more, they use mod and div as subroutines in defining addition -- which would be okay, but then to be theoretically sound you would want to make sure that you could define mod and div themselves without using addition as a subroutine!
Since you say efficiency is no concern, I propose using the usual definition of addition that mathematicians give, namely: 0 + y = y, and (x+1) + y = (x + y)+1. Here you should read +1 as a separate operation than addition, a more primitive one: the one that just increments a number. We spell it succ in Haskell (and its "inverse" is pred). With this theoretical definition in mind, the Haskell almost writes itself:
add :: Int -> Int -> Int
add 0 y = y
add x y = succ (add (pred x) y)
So: compared to other answers, we can take an Int and return an Int, and the only subroutines we use are ones that "feel" more primitive: succ, pred, and checking whether a number is zero or nonzero. (And we land at only three short lines of code... about a third as long as the shortest proposed alternative.) Of course the price we pay is very bad performance... try add (2^32) 0!
Like the other answers, this only works for positive numbers. When you are ready for handling negative numbers, we should chat again -- there's some fascinating mathematical tricks to pull.
I have a recursive Haskell function that takes a number n and generates a list that is n long of squared numbers from 1 up.
The code works but instead of the list for n=3 being [9,4,1] I want it to be [1,4,9].
sqNList :: Int -> [Int]
sqNList 0 = []
sqNList n = n*n : sqNList (n-1)
I've tried swappig the : for a ++ but then the pattern matching doesn't work. I have only just started Haskell today so may be obvious
The best approach is to implement sqNList in terms of a helper function that counts from 1 up to n. That way you can just generate the list in the correct order in the first place.
sqNList :: Int -> [Int]
sqNList n = sqNListHelper 1 n
sqNListHelper :: Int -> Int -> [Int]
sqNListHelper current end = ...
There are a wide variety of more sophisticated approaches, but this is the easiest approach to debug/test interactively that also has you figuring out how to do everything yourself.
More sophisticated approaches can include list comprehensions or composing functions like map and enumFromTo to build up the logic from simpler pieces.
The easiest approach that consumes probably the least amount of memory is to work with an accumulator: a parameter you pass and update through every recursive call.
Right now you use n as an accumulator, and decrement that, but we can decide to use an accumulator i instead that starts at 1, and keeps incrementing:
helper :: Int -> Int -> [Int]
helper i n | i > n = []
| otherwise = i*i : helper (i+1) n
Now we of course have to call it with i = 1 ourselves, which is not ideal, but we can use a where clause that scopes the helper in the sqNList:
sqNList :: Int -> [Int]
sqNList n = helper 1 n
where helper :: Int -> Int -> [Int]
helper i n | i > n = []
| otherwise = i*i : helper (i+1) n
Now we can improve this a bit. For instanc there is no need to pass n through the helper calls, since it does not change, and is defined at the top level:
sqNList :: Int -> [Int]
sqNList n = helper 1
where helper :: Int -> [Int]
helper i | i > n = []
| otherwise = i*i : helper (i+1)
There is furthermore no need to only work with Ints: we can use any type a for which Num a and Ord a:
sqNList :: (Num a, Ord a) => a -> [a]
sqNList n = helper 1
where helper i | i > n = []
| otherwise = i*i : helper (i+1)
This is a more advanced technique, so you may want to just save this for future study.
Most recursive functions tend to use one of the same general forms of recursion, so knowing which higher-order function to use saves you the effort of reimplementing (possibly incorrectly) the recursion, and lets you focus on the work that is unique to your problem.
This particular type of recursion is captured by the unfoldr function, defined in Data.List, which lets you generate a (possibly infinite) list using a generator function and an initial seed value.
Its definition can be as simple as
unfoldr f x = case f x of
Nothing -> []
Just (new, next) = new : unfoldr f next
although the actual definition is slightly more complicated for efficiency.
Essentially, you just call the generator f on the seed value x. If the result is Nothing, return an empty list. Otherwise, build a list containing a result and the list produced by a recursive call with a new seed value.
Applying this to your problem, we produce a square and the next integer as long as the input is still small enough.
import Data.List (unfoldr)
sqNList n = unfoldr generator 1
where generator x = if x > n then Nothing else Just (x*x, x+1)
So for a simple example like sqNList 3, it proceeds as follows:
Call generator 1 and get back Just (1, 2); the accumulator is now [1].
Call generator 2 and get back Just (4, 3); the accumulator is now
[1,4].
Call generator 3 and get back Just (9, 4); the accumulator is now [1,4,9].
Call generator 4 and get back Nothing. Return the accumulator [1,4,9] as the result.
Note that you generate the infinite list of all squares simply by never returning Nothing:
allSquares = unfoldr (\x -> Just (x*x, x+1)) 1
Haskell, being lazy, only generates elements in the list as you need them, so you could also define sqNList by taking only the first n items of the infinite list.
sqNList n = take n (unfoldr (\x -> Just (x*x, x+1)) 1)
I need to generate an infinite list based on two inputs.
gen :: Int -> Int -> [Int]
gen x y
Every element needs to be (x*y) and x is incremented by y each iteration and the original x must be in the list too.
So
gen 2 4
would result in
[2,8,24,40,..]
All of my attempts end up going forever (I use the call "take 4 (gen 2 4)" by in ghci the way) so I'm not sure how to proceed. Infinite lists just give me a lot of trouble.
I'm trying to do this through do-notation and the list monad. Any help in the right direction would be much appreciated.
EDIT
This was my last attempt which didnt work.
I'm learning Haskell through my friend and he gave me this problem to learn do notation for the list monad.
gen :: Int -> Int -> [Int]
gen x y =
do
a <- [x..]
guard $ mod a (x*y) == 0
let x = x+y
return a
I think you could create a List comprehension.
ghci> [2]++[(4*i+2)*4|i<-[0..]]
You can use this in your function. You can change variable x instead of number "2" and your "y" instead of the number "4". Try it.
Finally, I have made a concatenation (++) between the List Comprehension and a list with [2] (the variable x).
gen :: Int -> Int -> [Int]
gen x y = x : l
where l = fmap (\m -> y * (2 + m * y)) [0..]
testing:
take 5 $ gen 2 4
[2,8,24,40,56]
I have the following list (it’s a length 2 list, but in my assignment I have a length +n list)
xxs = [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
I’m trying to “replace” one 3-tuple (p1 or p2 or p3 or p4 from the image bellow) by list index (n) and by sub-list index (p).
The function, at the end, should be like:
fooo newtuple n p = (…)
For example: (replace p3 for (98,98,98):
fooo (98,98,98) 2 1
[(11, 22, [(33,33,33) , (44,44,44)]) , (55, 66, [(98,98,98),(88,88,88)])]
I planned the code like following this steps:
Access the pn that I want to change. I manage to achieve it by:
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
“replace” the 3-tuple. I really need some help here. I’m stuck. the best code (in my head it makes some sense) that I’ve done: (remember: please don’t be too bad on my code, I’ve only been studying Haskell only for 5 weeks)
foo n p newtuple = fooAux newtuple fob
where fooAux _ [] = []
fooAux m ((_):ds) = m:ds
fob n p = ((aux2 xxs)!!n)!!p
where aux2 [] = []
aux2 ((_,_,c):xs) = c:aux2 xs
Finally I will put all back together, using splitAt.
Is my approach to the problem correct? I really would appreciate some help on step 2.
I'm a bit new to Haskell too, but lets see if we can't come up with a decent way of doing this.
So, fundamentally what we're trying to do is modify something in a list. Using functional programming I'd like to keep it a bit general, so lets make a function update.
update :: Int -> (a -> a) -> [a] -> [a]
update n f xs = pre ++ (f val) : post
where (pre, val:post) = splitAt n xs
That will now take an index, a function and a list and replace the nth element in the list with the result of the function being applied to it.
In our bigger problem, however, we need to update in a nested context. Luckily our update function takes a function as an argument, so we can call update within that one, too!
type Triple a = (a,a,a)
type Item = (Int, Int, [Triple Int])
fooo :: Triple Int -> Int -> Int -> [Item] -> [Item]
fooo new n p = update (n-1) upFn
where upFn (x,y,ps) = (x,y, update (p-1) objFn ps)
objFn _ = new
All fooo has to do is call update twice (once within the other call) and do a little "housekeeping" work (putting the result in the tuple correctly). The (n-1) and (p-1) were because you seem to be indexing starting at 1, whereas Haskell starts at 0.
Lets just see if that works with our test case:
*Main> fooo (98,98,98) 2 1 [(11,22,[(33,33,33),(44,44,44)]),(55,66,[(77,77,77),(88,88,88)])]
[(11,22,[(33,33,33),(44,44,44)]),(55,66,[(98,98,98),(88,88,88)])]
First, we need a general function to map a certain element of a list, e.g.:
mapN :: (a -> a) -> Int -> [a] -> [a]
mapN f index list = zipWith replace list [1..] where
replace x i | i == index = f x
| otherwise = x
We can use this function twice, for the outer list and the inner lists. There is a little complication as the inner list is part of a tuple, so we need another helper function:
mapTuple3 :: (c -> c) -> (a,b,c) -> (a,b,c)
mapTuple3 f (x,y,z) = (x,y,f z)
Now we have everything we need to apply the replace function to our use case:
fooo :: Int -> Int -> (Int,Int,Int) -> [(Int,Int,[(Int,Int,Int)])]
fooo n p newTuple = mapN (mapTuple3 (mapN (const newTuple) p)) n xxs
Of course in the inner list, we don't need to consider the old value, so we can use const :: a -> (b -> a) to ignore that argument.
So you've tried using some ready-made function, (!!). It could access an item in a list for you, but forgot its place there, so couldn't update. You've got a solution offered, using another ready-made function split, that tears a list into two pieces, and (++) which glues them back into one.
But to get a real feel for it, what I suspect your assignment was aiming at in the first place (it's easy to forget a function name, and it's equally easy to write yourself a new one instead), you could try to write the first one, (!!), yourself. Then you'd see it's real easy to modify it so it's able to update the list too.
To write your function, best think of it as an equivalence equation:
myAt 1 (x:xs) = x
myAt n (x:xs) | n > 1 = ...
when n is zero, we just take away the head element. What do we do when it's not? We try to get nearer towards the zero. You can fill in the blanks.
So here we returned the element found. What if we wanted to replace it? Replace it with what? - this calls another parameter into existence,
myRepl 1 (x:xs) y = (y:xs)
myRepl n (x:xs) y | n > 1 = x : myRepl ...
Now you can complete the rest, I think.
Lastly, Haskell is a lazy language. That means it only calls into existence the elements of a list that are needed, eventually. What if you replace the 7-th element, but only first 3 are later asked for? The code using split will actually demand the 7 elements, so it can return the first 3 when later asked for them.
Now in your case you want to replace in a nested fashion, and the value to replace the old one with is dependent on the old value: newVal = let (a,b,ls)=oldVal in (a,b,myRepl p ls newtuple). So indeed you need to re-write using functions instead of values (so that where y was used before, const y would go):
myUpd 1 (x:xs) f = (f x:xs)
myUpd n ... = ...
and your whole call becomes myUpd n xxs (\(a,b,c)->(a,b,myUpd ... (const ...) )).
I started learning haskell yesterday and I got stuck on a problem. After a bit of trying different things I thought I'd finally come here and ask how to fix this. Also, feel free to criticize the way I have done things so far so I can know what direction to go. Thanks.
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
primes :: [Int]
primes = [x| x <- [1..],length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
lessen :: Int -> Int
lessen a = ceiling(sqrt(a))
To fix your type error, you want this:
lessen :: Int -> Int
lessen a = ceiling (sqrt (fromIntegral a))
a has type Int, but sqrt is expecting a floating point type, and the easiest way to convert an integral type to another numeric type is fromIntegral.
In addition to the type error in lessen you have a logic error in primes:
length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2
You're (rightly) only considering elements up to lessen x. This has the consequence that the list will almost never have exactly x - 2 elements. As a consequence you'll get into an infinite loop when trying to get more than two elements out of that list (because there is no 3rd element for which the condition is true, but haskell doesn't know that so it iterates to infinity trying to find it).
Also note that taking the length of a list is an O(n) operation and there's almost always a better way to achieve what you want.
As a style note, I would recommend defining a separate method isPrime. This will make your code look like this:
module Main where
main = putStrLn lastPrime
where
lastPrime :: String
lastPrime = show(last(take 10001 primes))
isPrime x = length [a| a <- [1..lessen(x)], mod x a /= 0] == x - 2]
primes :: [Int]
primes = [x| x <- [1..], isPrime x]
lessen :: Int -> Int
lessen a = ceiling(sqrt (fromIntegral a))
This IMHO makes the list comprehension much more readable. However it still contains the bug. To get rid of the bug, I'd suggest defining isPrime using a different approach. Going up to lessen x is fine (except you should start from 2 because 1 cleanly divides everything), but instead of building a new list with all the divisors, you should just check whether any of the numbers in the range divides x. For this we can use the higher order function any, so we get this:
isPrime x = not (any (\a -> mod x a == 0) [2 .. lessen x])