I think that the span function is Haskell is to apply a predicate to a list, and return a tuple where the first element is elements in the list that satisfy that predicate and the second element is the reminder of the list.
And it works well when I put:
span (<3) [1,2,4,5,6]. It just returns in GHCI:
([1,2], [4,5,6]).
However, when I enter span (>3) [1,2,4,5,6], it returns ([],[1,2,4,5,6]). But I thought it should return ([4,5,6],[1,2]). So I was wondering the reason of it .
Your understanding of span is not entirely correct, this is what the official docs say:
span, applied to a predicate p and a list xs,
returns a tuple where first element is longest prefix (possibly empty)
of xs of elements that satisfy p and second element
is the remainder of the list
(emphasis mine).
Hence, the predicate is applied to each element of the list starting from the beginning. This means that the predicate in
span (<3) [1,2,4,5,6]
is satisfied for the first two elements, and the result is
([1,2], [4,5,6])
But in this other example
span (>3) [1,2,4,5,6]
the first element of the list already doesn't satisfy the predicate, so the first element of the returned tuple will be an empty list.
What you describe here is partition :: (a -> Bool) -> [a] -> ([a], [a]). This is a function that for a given predicate will take a list, and make a 2-tuple where the first item is a list with items that satisfy the predicate, and the second item a list of items that do not satisfy the predicate. Indeed:
Prelude Data.List> partition (>3) [1,2,4,5,6]
([4,5,6],[1,2])
span :: (a -> Bool) -> [a] -> ([a], [a]) on the other hand makes a 2-tuple where the first item is the longest prefix of elements in the list that satisfy the predicate, and the second item is the list of remaining elements. Since for span (>3) [1,2,4,5,6], the first item does not satisfy the predicate. The longest prefix is the empty list [], and all elements of the given list, appear in the second item.
Basically span's complement is kind of break :: (a -> Bool) -> [a] -> ([a], [a]). You might even need to read the part twice in the docs to understand the subtle difference between break and span.
break, applied to a predicate p and a list xs, returns a tuple where
first element is longest prefix (possibly empty) of xs of elements
that do not satisfy p and second element is the remainder of the list:
So coming back to your question
λ> break (>3) [1,2,4,5,6]
([1,2],[4,5,6])
You may of course swap :: (a, b) -> (b, a) the tuple if that's essential. ie. swap . break
Another way to view the span function is to see it as consisting of both takeWhile and dropWhile function. i.e it is the application of both takeWhile and dropWhile function.
And what are these two functions?
takeWhile according to the documentation
takeWhile, applied to a predicate p and a list xs, returns the longest prefix (possibly empty) of xs of elements that satisfy p:
Basically it keeps returning elements from the list as long as the predicate is true. This means If the first element fails the predicate takeWhile will return []
dropWhile on the other hand, according to the documentation
dropWhile p xs returns the suffix remaining after takeWhile p xs
Basically it keeps skipping elements from the list while the predicate returns true. Once the predicate returns false, the remaining elements in the list is returned.
To see if the statement I made above about span being the application of both takeWhile and dropWhile function, we can apply these function independently to see their results.
Using just takeWhile:
*Main Data.List> takeWhile (>3) [1,2,4,5,6]
[]
Using just dropWhile:
*Main Data.List> dropWhile (>3) [1,2,4,5,6]
[1,2,4,5,6]
Now using span
*Main Data.List> span (>3) [1,2,4,5,6]
([],[1,2,4,5,6])
The result confirms span is applying both takeWhile and dropWhile
Note that what you describe here:
I think that the span function is Haskell is to apply a predicate to a list, and return a tuple where the first element is elements in the list that satisfy that predicate and the second element is the reminder of the list
Is the partition function as can be seen from the documentation
Related
I've written a function which search through a list of int-list to return the index of the list with an specific length by using pattern-matching:
let rec search x lst i = match lst with
| [] -> raise(Failure "Not found")
| hd :: tl -> if (List.length hd = x) then i else search x tl (i+1)
;;
For example:
utop # search 2 [ [1;2];[1;2;3] ] 0 ;;
- : int = 0
Is there a way to write a function with the same functionality using fold.left ?
What does List.fold_left actually do?
It takes (in reverse order to the order of arguments) a list, an initial value, and a function that works on that initial value and the first element in the list. If the list is empty, it returns the initial value. Otherwise it uses the function to update the initial value by way of recursion and works on the tail of the list.
let rec fold_left f init lst =
match lst with
| [] -> init
| x::xs -> fold_left f (f init x) xs
Now, what information do you need to keep track of as you iterate? The index. Easy enough.
But, what if you don't actually find a list of that length? You need to keep track of whether you've found one. So let's say we use a tuple of the index and a boolean flag.
Your function you pass to fold_left just needs to determine if a match has been found no update is necessary. Essentially we just no-op over the rest of the list. But, if we haven't found a match, then we need to test the current sublist's length and update the init value accordingly.
#glennsl (in a comment) and #Chris already explained that you may use List.fold_left but that it’s not the right tool for the job, because it processes the whole list whereas you want to stop once an occurrence is found. There are solutions but they are not satisfying:
(#Chris’ solution:) use a folding function that ignores the new elements once an occurrence has been found: you’re just wasting time, walking through the remaining tail for nothing;
evade the loop by throwing and catching an exception: better but hacky, you’re working around the normal functioning of List.fold_left.
I just mention that there is a generic function in the standard library that matches your situation almost perfectly:
val find : ('a -> bool) -> 'a list -> 'a
find f l returns the first element of the list l that satisfies the predicate f.
Raises Not_found if there is no value that satisfies f in the list l.
However it does not return the index, unlike what you are asking for. This is a deliberate design choice in the standard library, because list indexing is inefficient (linear time) and you shouldn’t do it. If, after these cautionary words, you still want the index, it is easy to write a generic function find_with_index.
Another remark on your code: you can avoid computing the lengths of inner lists fully, thanks to the following standard function:
val compare_length_with : 'a list -> int -> int
Compare the length of a list to an integer. compare_length_with l len is equivalent to compare (length l) len, except that the computation stops after at most len iterations on the list.
Since 4.05.0
So instead of if List.length hd = x, you can do if List.compare_length_with hd x = 0.
I am to use combinators and no for/while loops, recursion or defined library functions from F#'s List module, except constructors :: and []
Ideally I want to implement map
I am trying to write a function called llength that returns the list of the lengths of the sublists. For example llength [[1;2;3];[1;2];[1;2;3]] should return [3;2,3]. I also have function length that returns the length of a list.
let Tuple f = fun a b -> f (a, b)
let length l : int =
List.fold (Tuple (fst >> (+) 1)) 0 l
currently have
let llength l : int list =
List.map (length inner list) list
Not sure how I should try accessing my sublists with my restraints and should I use my other method on each sublist? any help is greatly appreciated, thanks!
Since this is homework, I don't want to just give you a fully coded solution, but here are some hints:
First, since fold is allowed you could implement map via fold. The folding function would take the list accumulated "so far" and prepend the next element transformed with mapping function. The result will come out reversed though (fold traverses forward, but you prepend at every step), so perhaps that wouldn't work for you if you're not allowed List.rev.
Second - the most obvious, fundamental way: naked recursion. Here's the way to think about it: (1) when the argument is an empty list, result should be an empty list; (2) when the argument is a non-empty list, the result should be length of the argument's head prepended to the list of lengths of the argument's tail, which can be calculated recursively. Try to write that down in F#, and there will be your solution.
Since you can use some functions that basically have a loop (fold, filter ...), there might be some "cheated & dirty" ways to implement map. For example, via filter:
let mymap f xs =
let mutable result = []
xs
|> List.filter (fun x ->
result <- f x :: result
true)
|> ignore
result |> List.rev
Note that List.rev is required as explained in the other answer.
I built a list of this structure:
[(Interger, Double)]
The List was created by using a zip over a list of Integers and a list of Doubles of exactly the same size.
Now I want to filter the list for Doubles that are either <18.5 or >25. The problem I have is I can't access the Doubles to use them in the filter function.
It's probably easy but I'm a bloody noob in this language. I googled around a lot and read some other threads but I didn't find an answer.
I got:
filter (<18.5) listexpression
So what I'm struggling with is that listexpression. It's easy if it's a list of single values. I could filter before zipping but then I can't connect the data from the filtered list to the other unfiltered List anymore.
Edit: I forgot to mention. It's a worksheet. We were asked to build filter and map functions ourselves and are not allowed to use any additions to the basic Haskell. Meaning no imports are allowed.
You can do something like this:
Prelude> filter (\p -> (snd p) < 18.5 || (snd p) > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]
The lambda function passed to filter, namely
(\p -> (snd p) < 18.5 || (snd p) > 25)
says that for every p, the second element of p must be less than 18.5 or over 25.
Alternatively, you could write it like this
Prelude> filter (\(_, f) -> f < 18.5 || f > 25) [(1, 2.3), (1, 20.0)]
[(1,2.3)]
Here the function says that for any pair whose first value doesn't matter and the second one is f, f must be less than 18.5 or over 25.
Glad to see Ami Tavory's answer solved your problem.
But under that answer, you commented:
I tried accessing it with a combination of (!!) but that didn't work.
With the insight of a teaching assistant [:D], I guess you confused list with tuple in Haskell.
zip returns a list of tuple, whereas (!!) take a list as (the first) argument (hence (!!1) take a single list argument), so (!!1) can't be applied to elements of the list returned by zip, which are of type tuple.
Prelude> :t zip
zip :: [a] -> [b] -> [(a, b)]
Prelude> :t (!!)
(!!) :: [a] -> Int -> a
Prelude> :t (!!1)
(!!1) :: [a] -> a
And you've known that fst and snd are applied to tuple.
Prelude> :t fst
fst :: (a, b) -> a
Prelude> :t snd
snd :: (a, b) -> b
A compact version using point free style would be
filter ((>18.5).snd) listexpression
This uses the function composition operator ., which reads as: First apply the snd function to a tuple from the list to extract the 2nd value, then apply the comparison to 18.5 to this value.
Just for a variety and some additional information which won't bite...
In Haskell the list type is an instance of Monad class. So a list operation like filter can simply be implemented by a monadic bind operator.
*Main> [(1,2.3),(3,21.2),(5,17.1),(4,24.4)] >>= \t -> if snd t < 25 && snd t > 18.5 then [t] else []
[(3,21.2),(4,24.4)]
Monad is all about handling the contained data in a sequential manner. In the list monad the contained data is the value within the list itself. So the bind operator can be very handy to access to contained values (tuples) of the monadic value (the list of tuples) in a sequential manner.
(>>=) :: Monad m => m a -> (a -> m b) -> m b
The type signature of the monadic bind operator states that it takes a monad type value m a as the first argument (the list of tuples here) and a function as the second argument which takes a pure value and returns a monadic value (takes a tuple and returns a tuple in a list or an empty list in this case).
\t -> if snd t < 25 && snd t > 18.5 then [t] else []
It's critical to understand how and why the list items are applied one by one to the provided function. An entire list is one monadic value and the contained values those accessed by the bind operator are passed to the provided a -> m b (take a pure value and return monadic value) type function. So all of the list items those applied to this function become a monadic value ([t] if condition satisfies or [] if it fails), are then concatenated by the bind operator to form one monadic return value (in this case a list of tuples those satisfy the condition which is implemented in the lambda function).
This monadic operation can also be implemented with the do notation
do
t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)]
if snd t < 25 && snd t > 18.5 then return t else []
[(3,21.2),(4,24.4)]
Of course this terribly resembles the list comprehensions which is in fact a syntactical sugar to the monadic list operations. So lets implement it for a final time by using the list comprehensions.
*Main> [t | t <- [(1,2.3),(3,21.2),(5,17.1),(4,24.4)], snd t < 25 && snd t > 18.5]
[(3,21.2),(4,24.4)]
I have "difficult" proplists. I need to get to serviceCatalog and traverse all its values untill I get one having name=me
J =[{<<"access">>,
{[{<<"token">>,
{[{<<"issued_at">>,<<"2015-09-12T13:27:38.789879">>},
{<<"expires">>,<<"2015-09-12T14:27:38Z">>},
{<<"id">>,<<"fe">>},
{<<"tenant">>,
{[{<<"description">>,null},
{<<"enabled">>,true},
{<<"id">>,<<"01">>},
{<<"name">>,<<"service">>}]}},
{<<"audit_ids">>,[<<"f">>]}]}},
{<<"serviceCatalog">>,
[{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"http://8.198.99.999:8080">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,
<<"http://8.198.99.999:8080/v1/AUTH_01a"...>>},
{<<"id">>,<<"30">>},
{<<"publicURL">>,<<"8.198.99.999:8080/v1/"...>>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"object-store">>},
{<<"name">>,<<"my">>}]},
{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"id">>,<<"4b3f44a5c64b4bd8b10c376c858b"...>>},
{<<"publicURL">>,<<"8.198.99.999:8080"...>>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"identity">>},
{<<"name">>,<<"other">>}]}]},
{<<"user">>,
{[{<<"username">>,<<"my">>},
{<<"roles_links">>,[]},
{<<"id">>,<<"8">>},
{<<"roles">>,[{[{<<"name">>,<<"admin">>}]}]},
{<<"name">>,<<"me">>}]}},
{<<"metadata">>,
{[{<<"is_admin">>,0},
{<<"roles">>,
[<<"e">>]}]}}]}}]
I am looking for the nice way to do it.
I started the implementation like that (but looks that there more elegant solution):
A1=proplists:get_value(<<"access">>,J).
A=element(1,A1).
B=proplists:get_value(<<"token">>, A).
C=element(1,B).
D=proplists:get_value(<<"serviceCatalog">>, C).
Any advices are wellcome
Given how deeply nested the data is, one approach is to write a set of recursive function clauses that can find a 2-tuple with a given key regardless of its level in the data. Here's an example:
-module(t).
-export([extract/2]).
extract(Key, Data) ->
extract(Key, Data, []).
extract(_Key, [], Acc) ->
Acc;
extract(Key, {Key,_}=KV, Acc) ->
[KV|Acc];
extract(Key, [{Key,_}=KV|Fields], Acc) ->
extract(Key, Fields, [KV|Acc]);
extract(Key, [{_,V}|Fields], Acc) when is_tuple(V); is_list(V) ->
extract(Key, Fields, extract(Key, V, Acc));
extract(Key, Data, Acc) when is_list(Data) ->
lists:foldl(fun(V, FoldAcc) when is_tuple(V); is_list(V) ->
extract(Key, V, FoldAcc);
(_, FoldAcc) ->
FoldAcc
end, Acc, Data);
extract(Key, Data, Acc) when is_tuple(Data) ->
extract(Key, tuple_to_list(Data), Acc).
The extract/2 function just passes its arguments along with an empty accumulator list to extract/3. The clauses of extract/3 work as described below:
The first clause checks if the data is an empty list, and if so, returns the accumulator.
The second clause matches the desired Key as the first element of a 2-tuple and adds that matching tuple to the accumulator.
The third clause matches the desired Key as the first element of a 2-tuple at the head of a list. It adds that matching tuple to the accumulator and continues extracting from other elements of the list.
The fourth clause handles the case of a 2-tuple without a matching key at the head of a list, where the value in the tuple is either a list or a tuple; if so, it attempts extraction from the value, and then continues with extracting from the rest of the list.
The fifth clause matches when Data is a list that doesn't match lists already matched by previous clauses. It folds over all values of the list, attempting extraction from all nested list and tuple values and ignoring all other values.
The sixth and final clause matches when Data is a tuple; it just converts the tuple to a list and calls extract/3 recursively.
Given the data J defined in the question, we can find a 2-tuple with a <<"serviceCatalog">> key like this:
1> SCs = t:extract(<<"serviceCatalog">>, J).
[{<<"serviceCatalog">>,
[{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"http://8.198.99.999:8080">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,
<<"http://8.198.99.999:8080/v1/AUTH_01a">>},
{<<"id">>,<<"30">>},
{<<"publicURL">>,<<"8.198.99.999:8080/v1/">>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"object-store">>},
{<<"name">>,<<"my">>}]},
{[{<<"endpoints">>,
[{[{<<"adminURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"region">>,<<"RegionOne">>},
{<<"internalURL">>,<<"8.198.99.999:8080/v2.0">>},
{<<"id">>,<<"4b3f44a5c64b4bd8b10c376c858b">>},
{<<"publicURL">>,<<"8.198.99.999:8080">>}]}]},
{<<"endpoints_links">>,[]},
{<<"type">>,<<"identity">>},
{<<"name">>,<<"other">>}]}]}]
The extraction found the element we expected. We can then pass that to further calls to t:extract/2 to see if the element we found contains the <<"name">> element we're seeking. We'll use a list comprehension that returns a list of tuples, each holding a <<"serviceCatalog">> element and a boolean indicating whether it contains the desired <<"name">> element:
2> [{SC,lists:any(fun({_, V}) -> V == <<"me">> end, t:extract(<<"name">>, SC))} || SC <- SCs].
The list comprehension walks over all the <<"serviceCatalog">> elements, extracting all <<"name">> tuples from each one and checking for any with a value of <<"me">>.
Unfortunately the <<"serviceCatalog">> element in the example data does not have a {<<"name">>, <<"me">>} tuple as described in the question, so the boolean in the result of the above list comprehension (the result is not shown) is false. But either way, to walk the result of the list comprehension, keep only the true values, but strip out the booleans so the resulting list contains only matching <<"serviceCatalog">> elements, we can fold over the list. First, let's make a fold function:
3> Fold = fun({SC, true}, Acc) -> [SC|Acc]; (_, Acc) -> Acc end.
#Fun<erl_eval.12.54118792>
Our fold function takes each {SC, boolean} tuple, adds those with true values to the accumulator list, and drops those with false values. Below we capture the result of the list comprehension from earlier, then pass it and the fold function to lists:foldl/3:
4> SCBools = [{SC,lists:any(fun({_, V}) -> V == <<"me">> end, t:extract(<<"name">>, SC))} || SC <- SCs].
...
5> lists:foldl(Fold, [], SCBools).
[]
Again, since no <<"serviceCatalog">> element in the data contains a {<<"name">>, <<"me">>} tuple, the resulting list here is empty, but if any did, we'd get their values in the list returned from lists:foldl/3.
How can I get the index of the element I am at in haskell when I am using map ?
For example I have this list l = "a+bc?|(de)*fg|h" and I want to know the exact index of the element I am at when I use the map or scanl function.
Amending Nikita Volkov's answer, you can use a function such as:
-- variant of map that passes each element's index as a second argument to f
mapInd :: (a -> Int -> b) -> [a] -> [b]
mapInd f l = zipWith f l [0..]
First of all, if you need an index when processing a list it is a certain sign that you're implementing a suboptimal algorithm, because list is not an index-based structure like array. If you need to deal with indexes you better consider using a vector instead.
Concerning your actual question, you can pair the items of your list with incrementing ints with the following code and then map over the result:
Prelude> zip [0..] "a+bc?|(de)*fg|h" :: [(Int, Char)]
[(0,'a'),(1,'+'),(2,'b'),(3,'c'),(4,'?'),(5,'|'),(6,'('),(7,'d'),(8,'e'),(9,')'),(10,'*'),(11,'f'),(12,'g'),(13,'|'),(14,'h')]