I need to create a list [1,2,3...n] without using pre implemented List fuctions. I can make the list backwards by writing :
fun makeList(x : int) =
if x = 0
then []
else x :: makeList(x-1)
Then I could reverse it and get [1,2,3,4] if inputting 4. How would I do this in only one function?
You've made the reverse list in one function and without using the List library.
To make it in the right order, you can use an accumulating argument:
fun makeList 0 result = result
| makeList n result = makeList (n-1) (n :: result)
Testing this:
- makeList 10 [];
> val it = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] : int list
This function takes an extra argument in which it accumulates the result in the right order.
This is what trips up other correspondents in this Q&A and what has made previous answerers delete their responses: Either you accept that this makeList takes an extra empty list as initial argument, which is kind of messy, or you nest this function inside another function that hides this mechanism:
fun makeList n =
let fun go 0 result = result
| go i result = go (i-1) (i :: result)
in go n [] end
But then you would not have used one function. Unless you mean one exposed function, since the inner function is only available in the context of the definition of makeList. As the problem statement is unclear about this, answering can be unsatisfactory.
Either you make one function, and allow for its type signature to be different (taking an extra argument), or you make one exposed function and allow for it to have an inner function that accumulates the result in reverse.
Related
I'm currently trying to solve the following exercise:
Given a list of Ints, count the number of times, an element is greater than the element that comes after it. The exercise forces me not to use explicit recursions.
Here are some example outputs given function :: [Int] -> Int:
function [1, 2, 3, 4, 5] == 0 -- only increasing numbers
function [5, 4, 3, 2, 1] == 4 -- only decreasing numbers
function [2, 1, 3, 1, 0, 4] == 3
-- 2 > 1
-- 3 > 1
-- 1 > 0
function [1] == 0 -- no successor
function [ ] == 0 -- no numbers at all
I imagined to use in some way foldl but after many attempts and not working idea I had to give up.
How can I count the number of times an element is greater than its successor without using recursion?
First we need to pair up the consecutive elements,
foo :: [Int] -> Int
foo xs = result
where
pairs = zip xs (drop 1 xs)
then we can process each pair
biggers = [ () | (x,y) <- pairs, x > y]
and now we can count them,
result = .......
All the nested names belong to the same, shared, nested scope. result must make use of the value of biggers, and biggers refers to the value of pairs which refers to the value of foo's parameter, xs. Make sure to put these code lines into the same definition, all indented by the same amount as the first one, for pairs, one under the other.
Actually using a left fold is also possible:
foo (h:t) = snd ( foldl' (\ (a, !c) x -> (x, if (a > x) then (c+1) else c))
(h,0) t )
foo [] = 0
I think you'll agree though that this is much less self-apparent than the first definition. Also note that it uses a "bang pattern", !, together with foldl', not foldl, to do the counting as soon as possible as we go along the input list, not delaying it until all the input list is traversed in full as foldl would do, needlessly, harming the overall efficiency.
Given a generic list, return a list containing the same objects in a tuple with their index in the list.
For example:
f ["a", "b"];
- val it = [(0,"a") , (1,"b")] : (int * string) list
The function should be a one-liner, meaning no pattern matching, recursion, if/else, helper functions and let/local. So far i could only make a list of indices given the input list:
fun f lst = List.take((foldl (fn (x,list) => [(hd(list)-1)]#list) [length(lst)] (lst)),length(lst));
f [#"a",#"b"];
- val it = [0, 1]: int List.list;
I should add the list items to these indices in a tuple but i'm not sure how to do that.
Here is a hint for one way to solve it:
1) Using List.sub, create an anonymous function which sends an index i to the pair consisting of i and the lst element at index i.
2) Map this over the result obtained by calling List.tabulate on length lst and the function which sends x to x.
I was able to get this to work (on one line), but the result is ugly compared to a straightforward pattern-matching approach. Other than as a puzzle, I don't see the motivation for disallowing that which makes SML an elegant language.
It appears that i forgot the #i operator to access the i'th element of a tuple. The answer is the following:
fun f xs = List.take((foldr (fn (x,list) => [(#1(hd(list))-1,x)]#list) [(length(xs),hd(xs))] (xs)),length(xs));
f (explode "Hello");
- val it = [(0, #"H"), (1, #"e"), (2, #"l"), (3, #"l"), (4, #"o")]: (int * char) List.list;
I'm a Haskell beginner,
I have a function
func :: Num a => [a] -> [a]
func [] = []
func (x:xs) = x + func xs
Each recursion I want to append the value to a list for my output. This function will sum consecutive indexes in a list so that the input [1, 2, 3, 4] produces [1, 3, 6, 10].
How do I append the value generated each time to my list?
Your problem here isn't how to append, but rather how to calculate the value in the first place. Each item needs to be substituted with a sum of itself with all the items preceding it.
Here is one way to do it:
Prelude> func (x:xs) = x:map (+ x) (func xs); func [] = []
Prelude> func [1, 2, 3, 4]
[1,3,6,10]
How does this work? We're given a list that starts with the element x and has the remaining elements xs. We want to increment every item in xs by x, after recursively applying the algorithm to xs.
This is what x:map (+ x) (func xs) does. It reads as "prepend x to the result of mapping every element in func xs through an increment by x".
E.g. for [1, 2, 3, 4], we want 1 to be added to every member of the result of recursively applying the algorithm to [2, 3, 4], then prepended. For [2, 3, 4] we want 2 to be ... to [3, 4]. And so on, until eventually for [4] we want 4 to be added and prepended to the result of applying the algorithm to [].
This is where our base case (func [] = []) kicks in: the algorithm is defined so that it returns an empty list unchanged. Hence func [4] is [4], func [3, 4] is [3, 7], and you keep incrementing and prepending until you get [1,3,6,10].
I think in this particular case, you could use scanl1 like:
scanl1 (+) [1,2,3,4] -- [1,3,6,10]
When iterating over lists, we often use folds, which is a way of reducing the list to a particular value.
There's also another type of operation, which is a fold that collects all results along the way, and that's called a scan (from the docs):
scanl = scanlGo
where
scanlGo :: (b -> a -> b) -> b -> [a] -> [b]
scanlGo f q ls = q : (case ls of
[] -> []
x:xs -> scanlGo f (f q x) xs)
So the scan takes three arguments: a function that takes two values and returns a value, a starter value, and a list of values.
The scan will then return a list.
Thus, what you need is a function that takes two values and returns something of the same type as the first (it's okay if both are the same). Binary addition would work here: +.
You also need a value to start off with (the b, which is the second argument to our function), and 0 is the identity for integer addition, so we should use that.
Finally, we pass your list to get the result.
Try to figure out how to write you function as a fold and then as a scan and you will discover the answer.
I would like to understand how sequential composition works much better than I do now in SML. I have to write a program that takes a list of integers and moves the integer at index zero to the last index in the list. ie. [4, 5, 6] -> [5, 6, 4].
The code I have right now is:
- fun cycle3 x =
= if length(x) = 1 then x
= else (List.drop(x, 1);
= x # [hd(x)]);
val cycle3 = fn : 'a list -> 'a list
The question lies in my else statement, what I want to happen is first concatenate the first term to the end, and then second drop the first term. It seems simple enough, I just don't understand how to perform multiple functions in a particular order using SML. My understanding was that the first function called has the scope of the second function that would have the scope of the third function.. etc etc.. What am I doing wrong here?
Most things in SML are immutable -- your function, rather than modifying the list, is building a new list. List.drop(x,1) evaluates to a new list consisting of all but the first element of x, but does not modify x.
To use your method, you would bind the result of List.drop(x,1) to a variable, as in the following:
fun cycle3 x = if length x = 1
then x
else let
val y = List.drop(x,1)
in
y # [hd(x)]
end
Alternately, a cleaner way of doing this same thing, that also handles the possibility of an empty list:
fun cycle3 [] = []
| cycle3 (x::xs) = xs # [x]
I am creating a sequence as a [Integer] in Haskell. The mathematical definition of the sequence is such that it repeats for some positive integers. In such a situation, I want to terminate the sequence and determine the length of the finite list.
My attempt at a solution is to first create an infinite list from the mathematical sequence. Then I want to filter the list for all elements until the first element repeats. The result should not include the repeating head of the list.
I have two questions/concerns here:
1) How do I match the head of the list to an element later in the list?
2) Is this an efficient method of solving my problem? (I will add more details about the exact sequence later if needed. For now I am looking for general comments.)
The algorithm that you described can simply be implemented like this:
findPeriodic :: Eq a => [a] -> [a]
findPeriodic [] = error "there are no periodic sequences in the empty list"
findPeriodic (x : xs) = x : takeWhile (/= x) xs
It does exactly what you describe: it takes the head of some list, and collects the part of the list up until that head element appears again in the list. So, for example:
list = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5, 1, ...]
findPeriodic list => [1, 2, 3, 4, 5]
The first element might never repeat in a sequence like 1,2,3,4,5,3,4,5,3,4, ... , where (a !! i) == (a !! j) ==> (a !! (i+1)) == (a !! (j+1)) (like you added in a comment, which is different from what you've asked for in the question).
This is known as cycle detection and was recently discussed e.g. here.