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).
Related
I'm currently working on an assignment. I have a function called gamaTipo that converts the values of a tuple into a data type previously defined by my professor.
The problem is: in order for gamaTipo to work, it needs to receive some preceding element. gamaTipo is defined like this: gamaTipo :: Peca -> (Int,Int) -> Peca where Peca is the data type defined by my professor.
What I need to do is to create a funcion that takes a list of tuples and converts it into Peca data type. The part that im strugling with is taking the preceding element of the list. i.e : let's say we have a list [(1,2),(3,4)] where the first element of the list (1,2) always corresponds to Dirt Ramp (data type defined by professor). I have to create a function convert :: [(Int,Int)] -> [Peca] where in order to calculate the element (3,4) i need to first translate (1,2) into Peca, and use it as the previous element to translate (3,4)
Here's what I've tried so far:
updateTuple :: [(Int,Int)] -> [Peca]
updateTuple [] = []
updateTuple ((x,y):xs) = let previous = Dirt Ramp
in (gamaTipo previous (x,y)): updateTuple xs
Although I get no error messages with this code, the expected output isn't correct. I'm also sorry if it's not easy to understand what I'm asking, English isn't my native tongue and it's hard to express my self. Thank you in advance! :)
If I understand correctly, your program needs to have a basic structure something like this:
updateTuple :: [(Int, Int)] -> [Peca]
updateTuple = go initialValue
where
go prev (xy:xys) =
let next = getNextValue prev xy
in prev : (go next xys)
go prev [] = prev
Basically, what’s happening here is:
updateTuple is defined in terms of a helper function go. (Note that ‘helper function’ isn’t standard terminology, it’s just what I’ve decided to call it).
go has an extra argument, which is used to store the previous value.
The implementation of go can then make use of the previous value.
When go recurses, the recursive call can then pass the newly-calculated value as the new ‘previous value’.
This is a reasonably common pattern in Haskell: if a recursive function requires an extra argument, then a new function (often named go) can be defined which has that extra argument. Then the original function can be defined in terms of go.
Hey guys I am having a problem with my code. The code below supposed to remove the first 2 in the list and then concatenate them.So the result answer would be 1,2.
first = [1,2,4,5,6,7] !! 0
second = [1,2,4,5,6,7] !! 1
newans = first ++ second
You can not remove elements from a list: Haskell is declarative meaning once you construct a list a, a will always work with the same list.
You can however construct a new list without the first two elements, and create a new list with the first two elements. For example:
get_remove_2 :: [a] -> ([a],[a])
get_remove_2 (a:b:cs) = ([a,b],cs)
We thus construct a new list with the first two elements with the [a,b] expression.
This function will take as input a list [a] and return a 2-tuple with as first element a list with two elements: the first two elements of the original list, and as second element the list where the first two elements are not present.
Note that this function will only work if the given list contains at least two elements. Otherwise it will error.
We're in the process of converting our imperative brains to a mostly-functional paradigm. This function is giving me trouble. I want to construct an array that EITHER contains two pairs or three pairs, depending on a condition (whether refreshToken is null). How can I do this cleanly using a FP paradigm? Of course with imperative code and mutation, I would just conditionally .push() the extra value onto the end which looks quite clean.
Is this an example of the "local mutation is ok" FP caveat?
(We're using ReadonlyArray in TypeScript to enforce immutability, which makes this somewhat more ugly.)
const itemsToSet = [
[JWT_KEY, jwt],
[JWT_EXPIRES_KEY, tokenExpireDate.toString()],
[REFRESH_TOKEN_KEY, refreshToken /*could be null*/]]
.filter(item => item[1] != null) as ReadonlyArray<ReadonlyArray<string>>;
AsyncStorage.multiSet(itemsToSet.map(roArray => [...roArray]));
What's wrong with itemsToSet as given in the OP? It looks functional to me, but it may be because of my lack of knowledge of TypeScript.
In Haskell, there's no null, but if we use Maybe for the second element, I think that itemsToSet could be translated to this:
itemsToSet :: [(String, String)]
itemsToSet = foldr folder [] values
where
values = [
(jwt_key, jwt),
(jwt_expires_key, tokenExpireDate),
(refresh_token_key, refreshToken)]
folder (key, Just value) acc = (key, value) : acc
folder _ acc = acc
Here, jwt, tokenExpireDate, and refreshToken are all of the type Maybe String.
itemsToSet performs a right fold over values, pattern-matching the Maye String elements against Just and (implicitly) Nothing. If it's a Just value, it cons the (key, value) pair to the accumulator acc. If not, folder just returns acc.
foldr traverses the values list from right to left, building up the accumulator as it visits each element. The initial accumulator value is the empty list [].
You don't need 'local mutation' in functional programming. In general, you can refactor from 'local mutation' to proper functional style by using recursion and introducing an accumulator value.
While foldr is a built-in function, you could implement it yourself using recursion.
In Haskell, I'd just create an array with three elements and, depending on the condition, pass it on either as-is or pass on just a slice of two elements. Thanks to laziness, no computation effort will be spent on the third element unless it's actually needed. In TypeScript, you probably will get the cost of computing the third element even if it's not needed, but perhaps that doesn't matter.
Alternatively, if you don't need the structure to be an actual array (for String elements, performance probably isn't that critical, and the O (n) direct-access cost isn't an issue if the length is limited to three elements), I'd use a singly-linked list instead. Create the list with two elements and, depending on the condition, append the third. This does not require any mutation: the 3-element list simply contains the unchanged 2-element list as a substructure.
Based on the description, I don't think arrays are the best solution simply because you know ahead of time that they contain either 2 values or 3 values depending on some condition. As such, I would model the problem as follows:
type alias Pair = (String, String)
type TokenState
= WithoutRefresh (Pair, Pair)
| WithRefresh (Pair, Pair, Pair)
itemsToTokenState: String -> Date -> Maybe String -> TokenState
itemsToTokenState jwtKey jwtExpiry maybeRefreshToken =
case maybeRefreshToken of
Some refreshToken ->
WithRefresh (("JWT_KEY", jwtKey), ("JWT_EXPIRES_KEY", toString jwtExpiry), ("REFRESH_TOKEN_KEY", refreshToken))
None ->
WithoutRefresh (("JWT_KEY", jwtKey), ("JWT_EXPIRES_KEY", toString jwtExpiry))
This way you are leveraging the type system more effectively, and could be improved on further by doing something more ergonomic than returning tuples.
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...
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 *)