I am developing a function in Haskell whose argument is a list of pairs. Recursively, this list will be split further until a base case is satisfied based on a predefined predicate. Usually, for simpler data types e.g. lists , literals could be used for base case matching, such as '[ ]'. How can I apply pattern matching using a boolean predicate?
The only way I came up with is using if else statement. But apparently this would lead to obvious problem.
The pattern
pure_instances [(_,_)] = True
pure_instances ((c1,_):(c2,attrs):xs) = (c1 == c2) && (pure_instances ((c2,attrs):xs))
The method
build_tree list = if (pure_instances list) then (Leaf get_label list) else (build_tree list)
build_ tree list = ...
I think you are looking for guards? (thanks Reid Barton)
build_tree list
| pure_instances list = Leaf get_label list
| otherwise = build_tree list
The infinite loop when pure_instances returns False is another matter...
Related
I would like to do the following:
let a = [1,2,3,4]
let res = []
for (i = 0; i < a.length; i++) {
if (someFilterFunction(x) == true) {
res.push(a[i])
}
}
return res
In Haskell, I assumed it would use takewhile but I need the function to not skip when the condition is not met.
We would like to do the following in Haskell: Write a function that takes a list as input, checks each element if it matches some test (aka predicate, filter function), include the element in a result list if the test succeeds.
So we want a function that accepts a list of some type of values (let's call them Ints) and returns a list:
timothyylim :: [Int] -> [Int]
That's the type signature (like a C prototype). Now we need the declaration. Because you are learning Haskell lets define this function without using any of the built in operations. What do we do when the input list is empty? Return an empty list!
timothyylim [] = []
What do we do when the list has at least one element?
timothyylim (firstElement : restOfList) =
-- What goes here?
Well we want to check if someFilterFunction firstElement is true and include that element along with the rest of the filtered list.
if someFilterFunction firstElement
then firstElement : timothyylim restOfList
And if it is false, then we just want to return the rest of the filtered list without this element.
else timothyylim restOfList
At this point we're done - we have a new function timothyylim that applies someFilterFunction to a list and generates a new list. There was no need to look at Prelude functions such as takeWhile - we did this using only language primitives including (in order of introduction) a type signature, case-by-case function declaration, pattern matching, if-then-else statements, function application, list concatenation, and primitive recursion.
In Real Use
In Haskell there is already a definition of a function named filter. It's like our filter except you'd pass in the filter function someFilterFunction as a parameter. So we could say:
timothyylim inputList = filter someFilterFunction inputList
Or equivalently:
timothyylim = filter someFilterFunction
Most of the time if your solution is a manual primitive recursive function, such as the timothyylim function above, then there's already a higher order function (i.e. a function that takes another function as a parameter) in Prelude that can do the job for you (see folds, maps, filters, and zips).
So i am currently working with Haskell at my college, but kinda struggling with pattern-matching and to be more specific i'll give the program, that i am to solve:
My function is awaiting a list of lists ( with each list containing at least 3 elements ) and in each list the second element is replaced with the number of the third element.
Example:
[[1,2,3],[4,5,6,7],[8,9,10]] should become [[1,3,3],[4,6,6,7],[8,10,10]
So far I've made the following:
f [] = []
f [[x]] = []
f [[x,y]] = []
f [[x,y,z]] = [[x,z,z]]
f ([x,y,z]:xs) = [x,z,z]:f(xs)
My questions are:
How can i identify, that some lists may contain more than 3 elements and that the list must remain the same, only the 2nd element changes.
How can i make the recursion, so that it handles exceptions (for example the first list has 4 elements).
Thank you in advance!
It may help to first write the function that swaps the second value in a list with the third.
swap (x:y:z:rest) = x:z:z:rest
swap xs = xs
In the above, x:y:z:rest matches a list of at least length 3. The value of rest, since it is at the end of the pattern, will match any kind of list, both empty and full. The second pattern match of xs is a catch-all for any other type of list, which will just return the same list if it is less than 3 items long.
From there, you can write f in terms of mapping over the outer list and applying swap:
f = map swap
I am new to SML programming and I have a problem to create a function to remove occurrences of an atom A from a list of integers. This list can be nested to any levels,
means we can have list like [1,2,3] and we can have list like [[1,2],[2,3]] as well as list like [[[1,2],[1,2]],[[2,3],[2,3]]].
So my problem is how can I check if the given item is a list or an atom as I have not found any such function in SMLNJ so far?
I have created a function that checks if the list is empty or not and then it calls a helper iterative function to check if the head of the list is a list or an atom. If it's an atom then replace it with another atom and continue with the rest of the tail.
Inside the helper function if I check that tail of the head of list is empty then it gives an error as tail function can have a list only.
So I have to do it like
tl([hd(a)), and if I do that, then it will always be empty.
If I apply it on the first list I get head as 1 and wrapping it in [] results in [1], so tail of this will be []. Same way if I get head of second list it will be [1,2] and wrapping it in [] will result in [[1,2]], so tail of this is again [].
So is there any way how I can check if the given item is an atom or again a list?
Thanks in advance for all responses.
"This list can be nested to any levels" is not possible in SML, because it's statically typed, and a list type has a specific element type. You either have an int list, which is a list whose elements are all int, or int list list, which is a list whose elements are all int list. You can't have a mixture.
The closest to what you are talking about would be to make an algebraic datatype with two cases, a leaf, or a nested list of elements of this datatype again. Then you can use pattern matching to deconstruct this datatype.
As stated in the other answer:
You could define your own data type
datatype 'a AtomList = Atom of 'a | List of 'a AtomList list
Then, with this data type you could define all the atom lists you mentioned above:
val x = List([Atom(1),Atom(2),Atom(3)])
val y = List([List([Atom(1),Atom(2)]),List([Atom(3),Atom(4)])])
val z = List([
List([
List([Atom(1),Atom(2)]),
List([Atom(1),Atom(2)]),
List([
List([Atom(2), Atom(3)]),
List([Atom(2), Atom(3)])
])
])
])
Then to go over your atom list, you would use pattern matching, as in:
fun show xs =
case xs of
Atom(x) => (*do something with atom*)
| List(ys) => (*do something with list of atoms *)
I have a question regarding Haskell that's been stumping my brain. I'm currently required to write a function that removes a string i.e. "word" from a list of strings ["hi", "today", "word", "Word", "WORD"] returns the list ["hi", "today", "Word", "WORD"]. I cannot use any higher-order functions and can only resort to primitive recursion.
Thinking about the problem, I thought maybe I could solve it by using a recursion where you search the head of the first string, if it matches "w" then compare the next head from the tail, and see if that matches "o". But then I soon realized that after all that work, you wouldn't be able to delete the complete string "word".
My question really being how do I compare a whole string in a list rather than only comparing 1 element at a time with something like: removeWord (x:xs). Is it even possible? Do I have to write a helper function to aid in the solution?
Consider the base case: removing a word from an empty list will be the empty list. This can be trivially written like so:
removeWord [] _ = []
Now consider the case where the list is not empty. You match this with x:xs. You can use a guard to select between these two conditions:
x is the word you want to remove. (x == word)
x is not the word you want to remove. (otherwise)
You don't need a helper function, though you could write one if you wanted to. You've basically got 3 conditions:
You get an empty list.
You get a list whose first element is the one you want to remove.
You get a list whose first element is anything else.
In other languages, you would do this with a set of if-else statements, or with a case statement, or a cond. In Haskell, you can do this with guards:
remove_word_recursive:: String -> [String] -> [String]
remove_word_recursive _ [] = []
remove_word_recursive test_word (x:xs) | test_word == x = what in this case?
remove_word_recursive test_word (x:xs) = what in default case?
Fill in the correct result for this function in these two conditions, and you should be done.
I think what you're looking for is a special case of the function sought for this question on string filters: Haskell - filter string list based on some conditions . Reading some of the discussion on the accepted answer might help you understand more of Haskell.
Since you want to remove a list element, it's easy to do it with List Comprehension.
myList = ["hi", "today", "word", "Word", "WORD"]
[x | x <- myList, x /= "word"]
The result is:
["hi","today","Word","WORD"]
If isInfixOf is not considered as higher order, then
import Data.List (isInfixOf)
filter (not . isInfixOf "word") ["hi", "today", "word", "Word", "WORD"]
I'm new to Haskell and I'm trying out a few tutorials.
I wrote this script:
lucky::(Integral a)=> a-> String
lucky 7 = "LUCKY NUMBER 7"
lucky x = "Bad luck"
I saved this as lucky.hs and ran it in the interpreter and it works fine.
But I am unsure about function definitions. It seems from the little I have read that I could equally define the function lucky as follows (function name is lucky2):
lucky2::(Integral a)=> a-> String
lucky2 x=(if x== 7 then "LUCKY NUMBER 7" else "Bad luck")
Both seem to work equally well. Clearly function lucky is clearer to read but is the lucky2 a correct way to write a function?
They are both correct. Arguably, the first one is more idiomatic Haskell because it uses its very important feature called pattern matching. In this form, it would usually be written as:
lucky::(Integral a)=> a-> String
lucky 7 = "LUCKY NUMBER 7"
lucky _ = "Bad luck"
The underscore signifies the fact that you are ignoring the exact form (value) of your parameter. You only care that it is different than 7, which was the pattern captured by your previous declaration.
The importance of pattern matching is best illustrated by function that operates on more complicated data, such as lists. If you were to write a function that computes a length of list, for example, you would likely start by providing a variant for empty lists:
len [] = 0
The [] clause is a pattern, which is set to match empty lists. Empty lists obviously have length of 0, so that's what we are having our function return.
The other part of len would be the following:
len (x:xs) = 1 + len xs
Here, you are matching on the pattern (x:xs). Colon : is the so-called cons operator: it is appending a value to list. An expression x:xs is therefore a pattern which matches some element (x) being appended to some list (xs). As a whole, it matches a list which has at least one element, since xs can also be an empty list ([]).
This second definition of len is also pretty straightforward. You compute the length of remaining list (len xs) and at 1 to it, which corresponds to the first element (x).
(The usual way to write the above definition would be:
len (_:xs) = 1 + len xs
which again signifies that you do not care what the first element is, only that it exists).
A 3rd way to write this would be using guards:
lucky n
| n == 7 = "lucky"
| otherwise = "unlucky"
There is no reason to be confused about that. There is always more than 1 way to do it. Note that this would be true even if there were no pattern matching or guards and you had to use the if.
All of the forms we've covered so far use so-called syntactic sugar provided by Haskell. Pattern guards are transformed to ordinary case expressions, as well as multiple function clauses and if expressions. Hence the most low-level, unsugared way to write this would be perhaps:
lucky n = case n of
7 -> "lucky"
_ -> "unlucky"
While it is good that you check for idiomatic ways I'd recommend to a beginner that he uses whatever works for him best, whatever he understands best. For example, if one does (not yet) understand points free style, there is no reason to force it. It will come to you sooner or later.