I'm trying to use map to return a list of lists. But i keep getting an error. I know map takes in a function and then uses that function. But i keep getting an error on it.
map (take 3) [1,2,3,4,5]
This is supposed to return [[1,2,3],[2,3,4],[3,4,5]], but it returns this error
<interactive>:6:1: error:
• Non type-variable argument in the constraint: Num [a]
(Use FlexibleContexts to permit this)
• When checking the inferred type
it :: forall a. Num [a] => [[a]]
is it hitting null is that why?
Let's take a look at exactly what the error message is saying.
map (take 3) [1, 2, 3, 4, 5]
map's type signature is
map :: (a -> b) -> [a] -> [b]
So it takes a function from a to b and returns a function from [a] to [b]. In your case, the function is take 3, which takes a list and returns a list. So a and b are both [t]. Therefore, the second argument to map should be [[t]], a list of lists. Now, Haskell looks at the second argument and sees that it's a list of numbers. So it says "How can I make a number into a list?" Haskell doesn't know of any good way to do that, so it complains that it doesn't know any type Num [t].
Now, as for what you meant to do, I believe it was mentioned in the comments. The tails function1 takes a list and returns the list of all tails of that list. So
tails [1, 2, 3, 4, 5]
-- ==> [[1, 2, 3, 4, 5], [2, 3, 4, 5], [3, 4, 5], [4, 5], [5], []]
Now you can apply the take function to each argument.
map (take 3) (tails [1, 2, 3, 4, 5])
-- ==> [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5], [5], []]
Oops! We've got some extra values we don't want. We only want the values that have three elements in them. So let's filter out the ones we don't want. filter takes a predicate (which is just a fancy way of saying "a function that returns a Boolean) and a list and returns a list containing only the elements that satisfy the predicate. The predicate we want is one that takes a list and returns whether or not that list has three elements.
\x -> ... -- We want only the lists
\x -> length x ... -- whose length
\x -> length x == 3 -- is exactly equal to 3
So that's our function. Now we pass that to filter.
filter (\x -> length x == 3) (map (take 3) (tails [1, 2, 3, 4, 5]))
-- ==> [[1, 2, 3], [2, 3, 4], [3, 4, 5]]
[1] Note that you may need to import Data.List to get the tails function.
Related
I would like to use a function that takes an enumerable and a function and does the same thing as Python's itertools.accumulate. For example,
iex> accumulate([1,3,7], &Kernel.+)
[1, 4, 11]
For an explanation, it's equal to [1, 1+2, 1+4+7]. Does such a function exist in Elixir's standard library?
Enum.scan/2 does the same thing.
Enum.scan([1, 3, 7], &+/2)
#⇒ [1, 4, 11]
I've written a function that dispatches on a vector of vectors of Integers. However, I get a MethodError when I try to use it:
julia> foo(x::Vector{Vector{<:Integer}}) = last(last(x));
julia> x = [[1], [2, 3], [4, 5, 6]]
3-element Array{Array{Int64,1},1}:
[1]
[2, 3]
[4, 5, 6]
julia> foo(x)
ERROR: MethodError: no method matching foo(::Array{Array{Int64,1},1})
Closest candidates are:
foo(::Array{Array{#s17,1} where #s17<:Integer,1}) at REPL[1]:1
Why doesn't this work?
The notation here is a little subtle. The parametric type that you've declared for the x argument, Vector{Vector{<:Integer}} is a shorthand notation for Vector{Vector{T} where T<:Integer}:
julia> Vector{Vector{<:Integer}}
Array{Array{#s17,1} where #s17<:Integer,1}
julia> Vector{Vector{T} where T<:Integer}
Array{Array{#s17,1} where #s17<:Integer,1}
Most importantly, note that Vector{Vector{T} where T<:Integer} is not equivalent to Vector{Vector{T}} where T<:Integer. In the former type, the concrete integer type of the inner vector elements can be different for each inner vector. In the latter type, all the inner vectors have elements of the same concrete integer type.
Furthermore, it is tricky to instantiate a literal array of type Vector{Vector{T} where T<:Integer}, because the literal array constructor promotes the types of its arguments:
julia> typeof([Int8(1), Int16(2)])
Array{Int16,1}
julia> typeof([Int8[1], Int16[2, 3]])
Array{Array{Int16,1},1}
However, it can be done as follows,
julia> foo(x::Vector{Vector{<:Integer}}) = last(last(x));
julia> y = Vector{<:Integer}[Int8[1], Int16[2, 3], Int32[4, 5, 6]]
3-element Array{Array{#s17,1} where #s17<:Integer,1}:
Int8[1]
Int16[2, 3]
Int32[4, 5, 6]
julia> foo(y)
6
where we have made extensive use of typed array initializers.
Alternatively, if you're fine with requiring the elements of each inner array to have the same concrete integer type, you could define your function as follows:
julia> bar(x::Vector{Vector{T}}) where T<:Integer = last(last(x));
julia> x = [[1], [2, 3], [4, 5, 6]]
3-element Array{Array{Int64,1},1}:
[1]
[2, 3]
[4, 5, 6]
julia> bar(x)
6
Note that this method won't accept a vector of vectors where the concrete integer types are different:
julia> bar(y)
ERROR: MethodError: no method matching bar(::Array{Array{#s17,1} where #s17<:Integer,1})
Closest candidates are:
bar(::Array{Array{T,1},1}) where T<:Integer at REPL[35]:1
For a related discussion, see the section of the Julia manual on UnionAll types.
I came away from Professor Frisby's Mostly Adequate Guide to Functional Programming with what seems to be a misconception about Maybe.
I believe:
map(add1, Just [1, 2, 3])
// => Just [2, 3, 4]
My feeling coming away from the aforementioned guide is that Maybe.map should try to call Array.map on the array, essentially returning Just(map(add1, [1, 2, 3]).
When I tried this using Sanctuary's Maybe type, and more recently Elm's Maybe type, I was disappointed to discover that neither of them support this (or, perhaps, I don't understand how they support this).
In Sanctuary,
> S.map(S.add(1), S.Just([1, 2, 3]))
! Invalid value
add :: FiniteNumber -> FiniteNumber -> FiniteNumber
^^^^^^^^^^^^
1
1) [1, 2, 3] :: Array Number, Array FiniteNumber, Array NonZeroFiniteNumber, Array Integer, Array ValidNumber
The value at position 1 is not a member of ‘FiniteNumber’.
In Elm,
> Maybe.map sqrt (Just [1, 2, 3])
-- TYPE MISMATCH --------------------------------------------- repl-temp-000.elm
The 2nd argument to function `map` is causing a mismatch.
4| Maybe.map sqrt (Just [1, 2, 3])
^^^^^^^^^^^^^^
Function `map` is expecting the 2nd argument to be:
Maybe Float
But it is:
Maybe (List number)
Similarly, I feel like I should be able to treat a Just(Just(1)) as a Just(1). On the other hand, my intuition about [[1]] is completely the opposite. Clearly, map(add1, [[1]]) should return [NaN] and not [[2]] or any other thing.
In Elm I was able to do the following:
> Maybe.map (List.map (add 1)) (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
Which is what I want to do, but not how I want to do it.
How should one map over Maybe List?
You have two functors to deal with: Maybe and List. What you're looking for is some way to combine them. You can simplify the Elm example you've posted by function composition:
> (Maybe.map << List.map) add1 (Just [1, 2, 3])
Just [2,3,4] : Maybe.Maybe (List number)
This is really just a short-hand of the example you posted which you said was not how you wanted to do it.
Sanctuary has a compose function, so the above would be represented as:
> S.compose(S.map, S.map)(S.add(1))(S.Just([1, 2, 3]))
Just([2, 3, 4])
Similarly, I feel like I should be able to treat a Just(Just(1)) as a Just(1)
This can be done using the join from the elm-community/maybe-extra package.
join (Just (Just 1)) == Just 1
join (Just Nothing) == Nothing
join Nothing == Nothing
Sanctuary has a join function as well, so you can do the following:
S.join(S.Just(S.Just(1))) == Just(1)
S.join(S.Just(S.Nothing)) == Nothing
S.join(S.Nothing) == Nothing
As Chad mentioned, you want to transform values nested within two functors.
Let's start by mapping over each individually to get comfortable:
> S.map(S.toUpper, ['foo', 'bar', 'baz'])
['FOO', 'BAR', 'BAZ']
> S.map(Math.sqrt, S.Just(64))
Just(8)
Let's consider the general type of map:
map :: Functor f => (a -> b) -> f a -> f b
Now, let's specialize this type for the two uses above:
map :: (String -> String) -> Array String -> Array String
map :: (Number -> Number) -> Maybe Number -> Maybe Number
So far so good. But in your case we want to map over a value of type Maybe (Array Number). We need a function with this type:
:: Maybe (Array Number) -> Maybe (Array Number)
If we map over S.Just([1, 2, 3]) we'll need to provide a function which takes [1, 2, 3]—the inner value—as an argument. So the function we provide to S.map must be a function of type Array (Number) -> Array (Number). S.map(S.add(1)) is such a function. Bringing this all together we arrive at:
> S.map(S.map(S.add(1)), S.Just([1, 2, 3]))
Just([2, 3, 4])
Is there a Qore operator/function to get sublist from a list without modifying source list, i.e. equivalent of substr(). extract operator removes items from original list.
list l = (1,2,3,4,5,6,7,8,9);
list l2 = extract l, 2, 4;
printf("l:%y\nl2:%y\n", l, l2);
l:[1, 2, 7, 8, 9]
l2:[3, 4, 5, 6]
select operator supports in condition argument $# macro expanded as index.
list l = (1,2,3,4,5,6,7,8,9);
list l2 = select l, $# >= 2 && $# <2+4;
printf("l:%y\nl2:%y\n", l, l2);
l:[1, 2, 3, 4, 5, 6, 7, 8, 9]
l2:[3, 4, 5, 6]
The select operator is the best solution as you stated in your answer to your own question.
The splice and extract operators both will modify the list operand, which is not what you want.
Note that there is an outstanding feature issue for this in Qore (1781) - not yet targeted to a release, but it could go in the next major release (0.8.13) if there is any interest.
I've been practicing using recursion to define the index in Erlang. Here I need to implement a function to return the index for a list from a list.
eg.
([2, 4, 4], [1, 1, 2, 4, 4, 3, 4 ]) ----> 2
([1, 3], [5, 2, 2, 3, 1, 3, 5]) ----> 4
([1], [3, 2, a, {1, 1}, 1] ----> 4
Here is my code:
-module(project).
-export([index/2]).
index([X|XS],[_]) -> index([X|XS],[_],1).
index(_,[],_) -> [];
index([X|XS],[X|_], ACC) -> ACC;
index([X|XS],[_|rest],ACC) ->index([X|XS],rest,ACC+1).
I modified and coded logically but it still can not being compiled. I hope someone who can help me with it. Thanks!
Just for fun, here is an implementation that is not written a very clean way, but illustrates the techniques I think you are looking for. Note there are two basic states: "checking" and "matching".
-module(sublistmatch).
-export([check/2]).
check(Segment, List) ->
SegLen = length(Segment),
ListLen = length(List),
Index = 1,
check(Segment, List, SegLen, ListLen, Index).
check(S, S, _, _, I) ->
{ok, I};
check(_, _, SL, LL, _) when SL >= LL ->
nomatch;
check(S = [H|Ss], [H|Ls], SL, LL, I) ->
case matches(Ss, Ls) of
true -> {ok, I};
false -> check(S, Ls, SL, LL - 1, I + 1)
end;
check(S, [_|L], SL, LL, I) ->
check(S, L, SL, LL - 1, I + 1).
matches([H|S], [H|L]) -> matches(S, L);
matches([], _) -> true;
matches(_, _) -> false.
Note that this depends on knowing the lengths of both the segment you are checking for, and the current length of the remaining list to check. Consider why this is necessary. Also consider how using the utility function matches/2 gives us a natural place to explore whether an option matches, and backtracks if it does not.
In real programs you would use the standard library functions such as lists:prefix/2, lists:suffix/2, or sets:is_subset/2, or maybe some key or member operation over a gb_tree, dict, map or array depending on the situation.
To Compile the code you have to change it to:
-module(project).
-export([index/2]).
%%index([X|XS],[_]) -> index([X|XS],[_],1).
index([X|XS],List) -> index([X|XS],List,1).
%% you shuld not pass '_' as parameter it's will be marked as unbound
index(_,[],_) -> [];
index([X|XS],[X|_], ACC) -> ACC;
%%index([X|XS],[_|rest],ACC) ->index([X|XS],rest,ACC+1).
index([X|XS],[_|Rest],ACC) ->index([X|XS],Rest,ACC+1).
%% rest is an atom, it's not the case you need to use here.
%%Variables should start with upper case letter.
This code will compiled but wrong results as some cases.