I am trying to learn Haskell from Haskell Road to Logic
and came across this example:
mnmInt :: [Int] -> Int
mnmInt [] = error "empty list"·
mnmInt [x] = x
mnmInt (x:xs) = min x (mnmInt xs)
I understand the functions takes a list of Int -
Checks if empty
if not
checks if it's a list with 1 int if so return x
if not
plug mnmInt with xs parameter to min.
how does it reach the base case? what does the xs stand for?
min implementation:
min' :: Int -> Int -> Int
min' x y | x <= y = x
| otherwise = y
doesn't take an array.
(x:xs) is pattern matching syntax. Pattern matching lets you "destructure" data types and bind them to names. In this case x is the head of the list, and xs is the tail. min' doesn't need to take a list because x is the head of the list, not a list itself.
min' itself finds the minimum value between two Ints, mnmInt will eventually expand out to something like (min' 1 (min' 2 (min' 3 4))) if you pass in a list that looks like [1,2,3,4].
This is easy to see if you evaluate the code by hand, which I highly suggest you try. Remember, (x:xs) is two names, which are the head and tail of the list. You might want to play around with constructing lists using :
Here is an example that shows how pattern matching relates to code flow.
foo (x:y:[]) = "two"
foo ([]) = "none"
foo (_) = "some other value"
if you call foo [1,2] it will output "two", if you do foo [1,2,3] it will give you "some other value", and if you do foo [] it will return "none"
You can write a list in two ways in Haskell, first like [1,2,3,4,5], which is only syntactic sugar for 1:2:3:4:5:[].
Now the pattern (x:xs) matches with a list like this:
head(x:xs) = x
--> head [1,2,3,4,5] = head 1:2:3:4:5:[] = head 1:xs = 1
i hope this example make it clear to you how a list pattern works.
Related
(I am currently doing an online course on Haskell and this is an exercise. I am not looking for answers, but simply for some pointers on how to proceed!)
I have trouble wrapping my head around this. In imperative languages I would simply use a loop, but since Haskell doesn't really have those I am left scratching my head.
I need to write a function nextIsGreater :: [Int] -> [Int] that, given a list of numbers, produces a list with all elements of the input list such that the element is followed by a greater number in the input list (the next number is greater).
Here is what I've managed to come up with so far.
nextIsGreater :: [Int] -> [Int]
nextIsGreater xs = [x | x <- init xs, y <- tail xs, x < y]
So far it works if I have only two numbers in the list. Say [0,5], it returns [0] as it is supposed to. If I have, say [0,5,6] then my code seems to check the 0 against both of the next numbers in the list and returns [0,0,5], when it should return [0,5]. How could I compare each adjacent number to eachother?
Not a bad attempt, but
[x | x <- init xs, y <- tail xs, x < y]
corresponds to a nested loop: you choose x from init xs, and then for each of these choices you pick all possible y from tail xs.
To make the idea work as intended, you'd need to use {-# LANGUAGE ParallelListComp #-} or equivalently zip the sources:
nextIsGreater xs = [x | (x,y) <- zip (init xs) (tail xs), x<y]
But there's a simpler way to obtain all choices of two consecutive elements, with tails:
nextIsGreater xs = [x | (x:y:_) <- tails xs, x<y]
The intention of this exercise is almost certainly to have you write a standard recursive solution using pattern matching, not use list comprehensions or higher level functions or anything like that.
If the course is any good, you should already have covered some recursive list-to-list transformations, functions with definitions of the form:
foo :: [Int] -> [Int]
foo (x:xs) = ... something involving "x" and "foo xs" ...
foo [] = ...
or similar, and you're expected to write something along the same lines.
Here's a first hint, with further spoilers below.
A simple way of writing a recursive function that operates on adjacent elements of lists is to write a pattern that names the first two elements:
foo (x:y:zs) = ...
The "..." can operate on x and y, and then perform a recursive call to process the "rest" of the list. The recursive call might be either foo zs or foo (y:zs) (or switch between those based on some condition), depending on what the function is doing.
Because this pattern will only match lists with at least two elements, you will usually also need patterns to match both one-element and empty lists:
foo [x] = ...
foo [] = ...
If that's not clear enough, let me refresh your memory on basic recursive list-to-list transformations starting with an example that doesn't inspect adjacent elements.
SPOILERS
.
.
.
Suppose we want to filter out all even elements from a list. A recursive solution would consider the two cases:
evens (x:xs) = ...
evens [] = ...
For the first case, the extraction of all evens from x:xs either includes x plus all the evens from xs (i.e., evens xs) or excludes x and includes only evens xs, depending on whether or not x itself even:
evens (x:xs) | even x = ...
| otherwise = ...
In particular, if x is even, the answer should include x together with evens xs:
evens (x:xs) | even x = x : evens xs
and if x is odd, the answer just should include evens xs:
| otherwise = evens xs
The final case is the subset of even numbers from the empty list, which is just the empty list:
evens [] = []
giving the complete definition:
evens :: [Int] -> [Int]
evens (x:xs) | even x = x : evens xs
| otherwise = evens xs
evens [] = []
The main difference in your example is that the decision to include x depends not only on x but on the element appearing after x, so let's consider a slightly different problem: take a list and output all elements that are followed by an even number.
We might consider starting with a similar structure:
beforeEvens (x:xs) | ... = x : beforeEvens xs -- include x
| otherwise = beforeEvens xs -- exclude x
beforeEvens [] = []
where "..." checks to see if the element after x (i.e., the first element of xs) is even. For example, we might call a separate function to check this:
beforeEvens (x:xs) | headIsEven xs = x : beforeEvens xs
| otherwise = beforeEvens xs
beforeEvens [] = []
You ought to be able to write a decent definition of headIsEven to complete this. Bonus points if instead of using head, it uses pattern matching. Note the special case headIsEven [] should return False.
A more direct approach, though, is to take advantage of the fact that patterns can be used to examine multiple elements at the start of the list. Here, we match a pattern that names the first two elements x and y, plus the rest of the list zs:
beforeEvens (x:y:zs) | even y = x : beforeEvens (y:zs)
| otherwise = beforeEvens (y:zs)
beforeEvens [x] = []
beforeEvens [] = []
Note a couple of tricky points here. If we match against the pattern (x:y:zs), then we have to be careful about whether we recurse on y:zs or zs alone. It depends on whether y should or shouldn't be considered for inclusion in the output. Also, the pattern (x:y:zs) won't match a singleton list, so we need an extra pattern match on that.
Because the last two cases are the same, we can combine them into a single case:
beforeEvens (x:y:zs) | even y = x : beforeEvens (y:zs)
| otherwise = beforeEvens (y:zs)
beforeEvens _ = []
You should find it relatively straightforward to modify beforeEvens to write your nextIsGreater function.
I tried with something like this but it doesn't work how I wanted it to do. I'm new kinda new to Haskell, and I don't really know how to do it, and what's wrong.
insert a (x:xs) = insert2 a (x:xs) []
where insert2 el (x:xs) hd =
if (x:xs) == []
then []
else if ( a>=x && a < head(xs))
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd++[x]
main = do
let list =[1 ,2 ,3 ,4 ,5 ,6]
let out = insert 2 list
print out
The output I get is [2,2,3,4,5,6,1]
First a couple of cosmetics:
Ensure indentation is right. When copy/pasting into StackOverflow, it's generally best to use ctrl+k to get it in code-block style.
There's no point matching (x:xs) only to pass the entire thing into your local function.
Omit unnecessary parentheses and use standardised spacing.
With that, your code becomes
insert a allxs = insert2 a allxs []
where insert2 el (x:xs) hd =
if x:xs == []
then []
else if a >= x && a < head xs
then hd ++ [x] ++ [a] ++ xs
else insert2 a xs hd ++ [x]
main = do
let list = [1, 2, 3, 4, 5, 6]
let out = insert 2 list
print out
Algorithmically speaking, there's no point in using an “accumulator argument” here. It's easier and actually more efficient to directly recurse on the input, and simply pass on the remaining tail after done with the insertion. Also remember to have a base case:
insert a [] = [a]
insert a (x:xs) = ...
You also don't need to use head. You've already pattern-matched the head element with the x:xs pattern. If you did need another list element, you should match that right there too, like
insert a (x:x':xs) = ...
...but you don't in fact need that, x is enough to determine what to do. Namely,
insert a (x:xs)
| a<=x = -- if the list was ordered, this implies that now _all_
-- its elements must be greater or equal a. Do you
-- need any recursion anymore?
| otherwise = -- ok, `x` was smaller, so you need to insert after it.
-- Recursion is needed here.
Here are some hints. It's a lot simpler than you're making it. You definitely don't need a helper function.
insert a [] = ??
insert a (x : xs)
| a <= x = ???
| otherwise = ???
Two things:
Prepending to a list is more efficient than appending to one.
Haskell lets you write separate definitions to avoid having to write single, nested conditional expressions.
There are two kinds of list you can insert into: empty and non-empty. Each can be handled by a separate definition, which the compiler will use to define a single function.
insert a [] = [a]
insert a (x:xs) = ...
The first case is easy: inserting into an empty list produces a singleton list. The second case is tricker: what you do depends on whether a is smaller than x or not. You can use a conditional expression
insert a (x:xs) = if a < x then a : insert x xs else x : insert a xs
thought you may see guards used instead:
insert a (x:xs) | a < x = a : insert x xs
| otherwise = x : insert a xs
In both cases, we know (because the list argument is already sorted) that insert x xs == x : xs, so we can write that directly to "short-circuit" the recursion:
insert a (x:xs) = if a < x then a : x : xs else x : insert a xs
don't complicate! , make simple ...
insertme a list = takeWhile (<a) list ++ [a] ++ dropWhile (<a) list
I'm beginner in haskell and I tried to add a number in a 2D list with specific index in haskell but I don't know how to do
example i have this:
[[],[],[]]
and I would like to put a number (3) in the index 1 like this
[[],[3],[]]
I tried this
[array !! 1] ++ [[3]]
but it doesn't work
As you may have noticed in your foray so far, Haskell isn't like many other languages in that it is generally immutable, so trying to change a value, especially in a deeply nested structure like that, isn't the easiest thing. [array !! 1] would give you a nested list [[]] but this is not mutable, so any manipulations you do this structure won't be reflected in the original array, it'll be a separate copy.
(There are specialized environments where you can do local mutability, as with e.g. Vectors in the ST monad, but these are an exception.)
For what you're trying to do, you'll have to deconstruct the list to get it to a point where you can easily make the modification, then reconstruct the final structure from the (modified) parts.
The splitAt function looks like it will help you with this: it takes a list and separates it into two parts at the index you give it.
let array = [[],[],[]]
splitAt 1 array
will give you
([[]], [[],[]])
This helps you by getting you closer to the list you want, the middle nested list.
Let's do a destructuring bind to be able to reconstruct your final list later:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
Next, you'll need to get at the sub-list you want, which is the first item in the end list:
desired = head end
Now you can make your modification -- note, this will produce a new list, it won't modify the one that's there:
desired' = 3:desired
Now we need to put this back into the end list. Unfortunately, the end list is still the original value of [[],[]], so we'll have to replace the head of this with our desired' to make it right:
end' = desired' : (tail end)
This drops the empty sub-list at the beginning and affixes the modified list in its place.
Now all that's left is to recombine the modified end' with the original beginning:
in beginning ++ end'
making the whole snippet:
let array = [[],[],[]]
(beginning, end) = splitAt 1 array
desired = head end
desired' = 3:desired
end' = desired' : (tail end)
in beginning ++ end'
or, if you're entering all these as commands in the REPL:
let array = [[],[],[]]
let (beginning, end) = splitAt 1 array
let desired = head end
let desired' = 3:desired
let end' = desired' : (tail end)
beginning ++ end'
As paul mentions, things in Haskell are immutable. What you want to do must be done not be modifying the list in place, but by destructuring the list, transforming one of its parts, and restructuring the list with this changed part. One way of destructuring (via splitAt) is put forth there; I'd like to offer another.
Lists in Haskell are defined as follows:
data [] a = [] | a : [a]
This reads "A list of a is either empty or an a followed by a list of a". (:) is pronounced "cons" for "constructor", and with it, you can create nonempty lists.
1 : [] -> [1]
1 : [2,3] -> [1,2,3]
1 : 2 : 3 : [] -> [1,2,3]
This goes both ways, thanks to pattern matching. If you have a list [1,2,3], matching it to x : xs will bind its head 1 to the name x and its tail [2,3] to xs. As you can see, we've destructured the list into the two pieces that were initially used to create it. We can then operate on those pieces before putting the list back together:
λ> let x : xs = [1,2,3]
λ> let y = x - 5
λ> y : xs
[-4,2,3]
So in your case, we can match the initial list to x : y : z : [], compute w = y ++ [3], and construct our new list:
λ> let x : y : z : [] = [[],[],[]]
λ> let w = y ++ [3]
λ> [x,w,z]
[[],[3],[]]
But that's not very extensible, and it doesn't solve the problem you pose ("with specific index"). What if later on we want to change the thousandth item of a list? I'm not too keen on matching that many pieces. Fortunately, we know a little something about lists—index n in list xs is index n+1 in list x:xs. So we can recurse, moving one step along the list and decrementing our index each step of the way:
foo :: Int -> [[Int]] -> [[Int]]
foo 0 (x:xs) = TODO -- Index 0 is x. We have arrived; here, we concatenate with [3] before restructuring the list.
foo n (x:xs) = x : foo (n-1) xs
foo n [] = TODO -- Up to you how you would like to handle invalid indices. Consider the function error.
Implement the first of those three yourself, assuming you're operating on index zero. Make sure you understand the recursive call in the second. Then read on.
Now, this works. It's not all that useful, though—it performs a predetermined computation on a specified item in a list of one particular type. It's time to generalize. What we want is a function of the following type signature:
bar :: (a -> a) -> Int -> [a] -> [a]
where bar f n xs applies the transformation f to the value at index n in the list xs. With this, we can implement the function from before:
foo n xs = bar (++[3]) n xs
foo = bar (++[3]) -- Alternatively, with partial application
And believe it or not, changing the foo you already wrote into the much more useful bar is a very simple task. Give it a try!
I've been doing a lot of practice recently in sml and one problem I've found in my textbook was asking to create a function that applies a function to the odd indexed values in a list. When trying to solve this I don't really understand how to get every other value. for instance
fun something f [] = 0
| something f (x:xs) =
Here above I know that we can get the values in order via the x value but is there a way to now apply this to get only odd indexed values? Sorry if this is a simple question sml has been an interesting but confusing language.
You can "destructure" the list with pattern matching in that case too – patterns can be arbitrarily complex.
For instance, a::b::bs matches a list with at least two elements, a::b::c::bs at least three, and so on.
If we index the first element 1:
fun everyOther _ [] = []
| everyOther f [x] = [f x]
| everyOther f (x::y::xs) = (f x)::y::(everyOther f xs)
Test:
val everyOther = fn : ('a -> 'a) -> 'a list -> 'a list
val it = () : unit
- fun square x = x * x;
val square = fn : int -> int
- everyOther square [1,2,3,4];
val it = [1,2,9,4] : int list
- everyOther square [1,2,3,4,5];
val it = [1,2,9,4,25] : int list
The case of the first element being indexed 0 rather than 1 left as an exercise.
I have a function in SML that returns a nested list:
[["A", "B", "C"], ["A", "B"], ["B", "C"]]]
Is it possible to extract the elements that appear in these lists? i.e. output "B"?
I've tried something to the effect of List.filter (fn y=>(fn x=> x=y)) lst but to no avail..
Any hints?
I'll assume that the example nested list you give is representative, i.e., that elements are unique and ordered. I'll additionally leave out any explicit types or parameterized comparison functions, so the functions will operate on integers, not strings.
First, break down the problem down into comparing lists pairwise. Define a helper function common to find the common elements of a pair of ordered lists. It could look like this:
fun common(xs, []) = []
| common([], ys) = []
| common(x::xs, y::ys) = if x=y then x::common(xs, ys)
else if x < y then common(xs, y::ys)
else common(x::xs, ys)
It has type int list * int list -> int list.
To make this work for the nested list, you can base a solution on common, along the lines of:
fun nested_common([]) = []
| nested_common(x::[]) = x
| nested_common(x::y::rest) = nested_common(common(x,y)::rest)
This has type int list list -> int list.
Putting it to use (in Moscow ML):
- nested_common [[1,2,3], [1,2], [2,3]];
> val it = [2] : int list