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)
Related
I'm having a hard time getting Haskell and functional programming together in my head. What I am trying to do is manipulate a string so that I am printing/returning specific characters each time based on a number given. For example:
printing "testing" 2 = "etn"
printing "testing" 3 = "sn"
I've read a lot online, and from what I understand I can achieve this with filtering and cycling, but I cannot get/understand the syntax of this language to get a working program.
I'll try to describe my thought process so you can follow. This function fits the pattern of creating an output list (here a string) from an input seed (here a string) by repeated function application (here dropping some elements). Thus I choose an implementation with Data.List.unfoldr.
unfoldr :: (b -> Maybe (a, b)) -> b -> [a]
Okay so, I need to turn the seed b into (Maybe) an output a and the rest of the string. I'll call this subfunction f and pass it into unfoldr.
printing s n = unfoldr f s
where f b = case drop n b of
[] -> Nothing
(x:xs) -> Just (x,xs)
It turns out that attempting to take the head off the front of the list and returning a Maybe is also a common pattern. It's Data.List.uncons, so
printing s n = unfoldr (uncons . drop n) s
Very smooth! So I test it out, and the output is wrong! Your specified output actually eg. for n=2 selects every 2nd character, ie. drops (n-1) characters.
printing s n = unfoldr (uncons . drop (n-1)) s
I test it again and it matches the desired output. Phew!
To demonstrate the Haskell language some alternative solutions to the accepted answer.
Using list comprehension:
printing :: Int -> String -> String
printing j ls = [s | (i, s) <- zip [1 .. ] ls, mod i j == 0]
Using recursion:
printing' :: Int -> String -> String
printing' n ls
| null ls' = []
| otherwise = x : printing' n xs
where
ls' = drop (n - 1) ls
(x : xs) = ls'
In both cases I flipped the arguments so it is easier to do partial application: printing 5 for example is a new function and will give each 5th character when applied to a string.
Note with a minor modification they will work for any list
takeEvery :: Int -> [a] -> [a]
As a short exercise in using Haskell arrays I wanted to implement a function giving the first n (odd) prime numbers. The code below (compiled with GHC 7.10.3) produces a loop error at runtime. "A Gentle Introduction to Haskell" uses recursive calls in array creation to compute Fibonacci numbers (https://www.haskell.org/tutorial/arrays.html, 13.2, code below for reference), which works just fine. My question is:
Where is the difference between the two ways of recursive creation? Which recursive calls are generally allowed when creating arrays?
My code:
import Data.Array.Unboxed
main = putStrLn $ show $ (primes 500)!500 --arbitrary example
primes :: Int -> UArray Int Int
primes n = a
where
a = array (1,n) $ primelist 1 [3,5..]
primelist i (m:ms) =
if all (not . divides m) [ a!j | j <- [1..(i-1)]]
then (i ,m) : primelist (succ i) ms
else primelist i ms
divides m k = m `mod` k == 0
Code from "A Gentle Introduction to Haskell":
fibs :: Int -> Array Int Int
fibs n = a where a = array (0,n) ([(0, 1), (1, 1)] ++
[(i, a!(i-2) + a!(i-1)) | i <- [2..n]])
Thanks in advance for any answers!
Update: I think I finally understood what's going on. array is lazy on the list elements, but is unnecessarily strict on its spine!
This causes a <<loop>> exception, for instance
test :: Array Int Int
test = array (1,2) ((1,1) : if test!1 == 1 then [(2,2)] else [(2,100)])
unlike
test :: Array Int Int
test = array (1,2) ((1,1) : [(2, if test!1 == 1 then 2 else 100)])
So, recursion works as long as it only affects the values.
A working version:
main :: IO ()
main = do
putStrLn $ show $ (primes 500)!500 --arbitrary example
-- A spine-lazy version of array
-- Assumes the list carries indices lo..hi
arraySpineLazy :: (Int, Int) -> [(Int, a)] -> Array Int a
arraySpineLazy (lo,hi) xs = array (lo,hi) $ go lo xs
where
go i _ | i > hi = []
go i ~((_,e):ys) = (i, e) : go (succ i) ys
primes :: Int -> Array Int Int
primes n = a
where
a :: Array Int Int
a = arraySpineLazy (1,n) $ primelist 1 (2: [3,5..])
primelist :: Int -> [Int] -> [(Int, Int)]
primelist i _ | i > n = []
primelist _ [] = [] -- remove warnings
primelist i (m:ms) =
if all (not . divides m) [ a!j | j <- [1..(i-1)]]
then (i ,m) : primelist (succ i) ms
else primelist i ms
divides m k = m `mod` k == 0
Arguably, we should instead write a lazier variant of listArray instead, since our array variant discard the first components of the pair.
This is a strictness issue: you can't generate unboxed arrays recursively, only boxed (regular) ones, since only boxed ones have a lazy semantics.
Forget arrays, and consider the following recursive pair definition
let (x,y) = (0,x)
This defines x=0 ; y=0, recursively. However, for the recursion to work, it is necessary that the pair is lazy. Otherwise, it generates an infinite recursion, much as the following would do:
let p = case p of (x,y) -> (0,x)
Above, p evaluates itself before it can expose the (,) pair constructor, so an infinite loop arises. By comparison,
let p = (0, case p of (x,y) -> x)
would work, since p produces the (,) before calling itself. Note however that this relies on the constructor (,) not evaluating the components before returning -- it has to be lazy, and return immediately leaving the components to be evaluated later.
Operationally, a pair is constructed having inside tho thunks: two pointers to code, which will evaluate the result later on. Hence the pair is not really a pair of integers, but a pair of indirections-to-integer. This is called "boxing", and is needed to achieve laziness, even if it carries a little computational cost.
By definition, unboxed data structures, like unboxed arrays, avoid boxing, so they are strict, not lazy, and they can not support the same recursion approaches.
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.
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 ...) )).
The question is to compute the mode (the value that occurs most frequently) of a sorted list of integers.
[1,1,1,1,2,2,3,3] -> 1
[2,2,3,3,3,3,4,4,8,8,8,8] -> 3 or 8
[3,3,3,3,4,4,5,5,6,6] -> 3
Just use the Prelude library.
Are the functions filter, map, foldr in Prelude library?
Starting from the beginning.
You want to make a pass through a sequence and get the maximum frequency of an integer.
This sounds like a job for fold, as fold goes through a sequence aggregating a value along the way before giving you a final result.
foldl :: (a -> b -> a) -> a -> [b] -> a
The type of foldl is shown above. We can fill in some of that already (I find that helps me work out what types I need)
foldl :: (a -> Int -> a) -> a -> [Int] -> a
We need to fold something through that to get the value. We have to keep track of the current run and the current count
data BestRun = BestRun {
currentNum :: Int,
occurrences :: Int,
bestNum :: Int,
bestOccurrences :: Int
}
So now we can fill in a bit more:
foldl :: (BestRun -> Int -> BestRun) -> BestRun -> [Int] -> BestRun
So we want a function that does the aggregation
f :: BestRun -> Int -> BestRun
f (BestRun current occ best bestOcc) x
| x == current = (BestRun current (occ + 1) best bestOcc) -- continuing current sequence
| occ > bestOcc = (BestRun x 1 current occ) -- a new best sequence
| otherwise = (BestRun x 1 best bestOcc) -- new sequence
So now we can write the function using foldl as
bestRun :: [Int] -> Int
bestRun xs = bestNum (foldl f (BestRun 0 0 0 0) xs)
Are the functions filter, map, foldr in Prelude library?
Stop...Hoogle time!
Did you know Hoogle tells you which module a function is from? Hoolging map results in this information on the search page:
map :: (a -> b) -> [a] -> [b]
base Prelude, base Data.List
This means map is defined both in Prelude and in Data.List. You can hoogle the other functions and likewise see that they are indeed in Prelude.
You can also look at Haskell 2010 > Standard Prelude or the Prelude hackage docs.
So we are allowed to map, filter, and foldr, as well as anything else in Prelude. That's good. Let's start with Landei's idea, to turn the list into a list of lists.
groupSorted :: [a] -> [[a]]
groupSorted = undefined
-- groupSorted [1,1,2,2,3,3] ==> [[1,1],[2,2],[3,3]]
How are we supposed to implement groupSorted? Well, I dunno. Let's think about that later. Pretend that we've implemented it. How would we use it to get the correct solution? I'm assuming it is OK to choose just one correct solution, in the event that there is more than one (as in your second example).
mode :: [a] -> a
mode xs = doSomething (groupSorted xs)
where doSomething :: [[a]] -> a
doSomething = undefined
-- doSomething [[1],[2],[3,3]] ==> 3
-- mode [1,2,3,3] ==> 3
We need to do something after we use groupSorted on the list. But what? Well...we should find the longest list in the list of lists. Right? That would tell us which element appears the most in the original list. Then, once we find the longest sublist, we want to return the element inside it.
chooseLongest :: [[a]] -> a
chooseLongest xs = head $ chooseBy (\ys -> length ys) xs
where chooseBy :: ([a] -> b) -> [[a]] -> a
chooseBy f zs = undefined
-- chooseBy length [[1],[2],[3,3]] ==> [3,3]
-- chooseLongest [[1],[2],[3,3]] ==> 3
chooseLongest is the doSomething from before. The idea is that we want to choose the best list in the list of lists xs, and then take one of its elements (its head does just fine). I defined this by creating a more general function, chooseBy, which uses a function (in this case, we use the length function) to determine which choice is best.
Now we're at the "hard" part. Folds. chooseBy and groupSorted are both folds. I'll step you through groupSorted, and leave chooseBy up to you.
How to write your own folds
We know groupSorted is a fold, because it consumes the entire list, and produces something entirely new.
groupSorted :: [Int] -> [[Int]]
groupSorted xs = foldr step start xs
where step :: Int -> [[Int]] -> [[Int]]
step = undefined
start :: [[Int]]
start = undefined
We need to choose an initial value, start, and a stepping function step. We know their types because the type of foldr is (a -> b -> b) -> b -> [a] -> b, and in this case, a is Int (because xs is [Int], which lines up with [a]), and the b we want to end up with is [[Int]].
Now remember, the stepping function will inspect the elements of the list, one by one, and use step to fuse them into an accumulator. I will call the currently inspected element v, and the accumulator acc.
step v acc = undefined
Remember, in theory, foldr works its way from right to left. So suppose we have the list [1,2,3,3]. Let's step through the algorithm, starting with the rightmost 3 and working our way left.
step 3 start = [[3]]
Whatever start is, when we combine it with 3 it should end up as [[3]]. We know this because if the original input list to groupSorted were simply [3], then we would want [[3]] as a result. However, it isn't just [3]. Let's pretend now that it's just [3,3]. [[3]] is the new accumulator, and the result we would want is [[3,3]].
step 3 [[3]] = [[3,3]]
What should we do with these inputs? Well, we should tack the 3 onto that inner list. But what about the next step?
step 2 [[3,3]] = [[2],[3,3]]
In this case, we should create a new list with 2 in it.
step 1 [[2],[3,3]] = [[1],[2],[3,3]]
Just like last time, in this case we should create a new list with 1 inside of it.
At this point we have traversed the entire input list, and have our final result. So how do we define step? There appear to be two cases, depending on a comparison between v and acc.
step v acc#((x:xs):xss) | v == x = (v:x:xs) : xss
| otherwise = [v] : acc
In one case, v is the same as the head of the first sublist in acc. In that case we prepend v to that same sublist. But if such is not the case, then we put v in its own list and prepend that to acc. So what should start be? Well, it needs special treatment; let's just use [] and add a special pattern match for it.
step elem [] = [[elem]]
start = []
And there you have it. All you have to do to write your on fold is determine what start and step are, and you're done. With some cleanup and eta reduction:
groupSorted = foldr step []
where step v [] = [[v]]
step v acc#((x:xs):xss)
| v == x = (v:x:xs) : xss
| otherwise = [v] : acc
This may not be the most efficient solution, but it works, and if you later need to optimize, you at least have an idea of how this function works.
I don't want to spoil all the fun, but a group function would be helpful. Unfortunately it is defined in Data.List, so you need to write your own. One possible way would be:
-- corrected version, see comments
grp [] = []
grp (x:xs) = let a = takeWhile (==x) xs
b = dropWhile (==x) xs
in (x : a) : grp b
E.g. grp [1,1,2,2,3,3,3] gives [[1,1],[2,2],[3,3,3]]. I think from there you can find the solution yourself.
I'd try the following:
mostFrequent = snd . foldl1 max . map mark . group
where
mark (a:as) = (1 + length as, a)
mark [] = error "cannot happen" -- because made by group
Note that it works for any finite list that contains orderable elements, not just integers.