Does erlang have a hidden rownum on a list? - erlang

This is an example of my current code:
DataSet = [1,2,3,4,5,6,7,8,9].
Sequence = [3,4,5,6].
ReducedDataSet = lists:foldl( fun(SeqNumber, Output) ->
Row = lists:nth(SeqNumber, DataSet),
[Row|Output]
end,
[],
Sequence
).
ReducedDataSet ends up as [6,5,4,3] and if I change it to lists:foldr, ReducedDataSet would be [3,4,5,6].
I didn't expect this as when absorbed left to right, the 3rd value is 3 and should proceed to 6, but when absorbed right to left, the 3rd value would be 7, and proceed to 4.
Does this mean there's a hidden row number on my list, and foldl and foldr only differ in the sort order of the final list?

I think this is a more general fold question.
In general, fold performs the following: (new_element, acc) -> new_acc
If the operation new_element ° acc is commutative (e.g. the sum), foldl and foldr are the same.
If the operation is "append" there is a difference between appending the element to the left or to the right.
[3] ° 4 -> [3, 4] VS 4 ° [3] -> [4, 3]
I never remember which is foldl and foldr but I think left/right refers to the position of the accumulator ([3] ° 4 is foldl with this definition)

TL;DR
No, there is no hidden index or "row number" in an Erlang list.
Discussion
It may be helpful to explore the nature of list operations a bit more in the context of functional lists of the "lists are a bunch of conses" variety.
I wrote an explanation of folds a while back that might be useful to you: Explanation of lists:fold function
Keep in mind that functional lists only have pointers that go one-way. That is, they are singly linked lists. There is no concept of a "rownum" or "index" as it would be in a C style array. Each call to lists:nth/2 is actually traversing the list to the nth element before returning that element.
We could write lists:nth/2 like this if we want a version that crashes on bad input (and, looking it up, it turns out that it is written almost exactly like this):
nth(1, [Element | _]) ->
Element;
nth(N, [_ | Rest]) when N > 1 ->
lists:nth(N - 1, Rest).
(As a side note, consider not inlining funs that require you to write multi-line definitions as function arguments...)

Related

checking if enough elements in a F# list

Right now I have a few instances like this:
let doIt someList =
if someList |> List.truncate 2 |> List.length >= 2 then
someList[0] + someList[1]
else
0
I need to grab the top 2 elements of a list quite often to see changes, but in some cases I don't have enough elements and I need to make sure there are at least 2.
The best way I've found so far is to truncate the list before getting its length, but this creates allocations for no reason.
Is there a better method?
I think I would suggest pattern matching in this case:
let doIt someList =
match someList with
| a :: b :: _ -> a + b
| _ -> 0
Here, a and b are the ints in the list, while _ represents a discarded of list int. This way you don't have to pull the first two elements out of the list with an index, as they are already available as a and b. The last case of the match catches any pattern that was not matched earlier, such as cases with zero, one or three-or-more elements.
This should be a cheap operation, as F# lists are implemented as a singly linked list. So [a;b;c;d] would be represented as a::(b::(c::(d::[]))). a and b are matched, while the rest (c::(d::[])) is left untouched (and is put in the _ slot). It does not need to create a new list to do so.

Determine if all elements of a list belong to the same DU case

I have a discriminated union with 10-15 cases, all having data in the form of int<'a>:
type MyUnionType =
| Case1 of int<someUnit>
| Case2 of int<someUnit>
|
...
| CaseN of int<someOtherUnit>
I am new to functional programming and am struggling to write a function with the following signature:
mySum:MyUnionType option list -> MyUnionType option
The function should sum all the ints iff all the Some elements belong to the same DU case. For example:
mySum [Some (Case1 2<a>), Some (Case1 3<a>), None] = Some Case1 5<a>
mySum [Some (Case1 2<a>), Some (Case2 3<a>), None] = None
mySum [None] = None
I know about Option.map and List.choose and the likes that can help here, but I'm struggling with determining whether all elements belong to the same case.
Is there an elegant and FP-idiomatic way to write this function? (If it simplifies matters, you can assume the list is never empty.)
(Though I don't have a clear grasp on monoids/monads/morphisms yet, don't be afraid to use the words if relevant, though please stop a bit short of zygohistomorphic prepromorphisms).
First, the code I'm about to present you will be greatly simplified if you remove all the None cases from the list before summing it. So for the rest of my answer, I'm going to assume that you've run your list through a List.choose id step first to get rid of all the None values.
The simplest way to think about this is probably to break it down into a series of single steps. You start by taking the first item of the list to initialize your "sum so far" value. (If there was no first item after running the list through List.choose id, then the list was either empty or contained only Nones, so the sum in that case will be None). Now, if that was the only item of the list, then you've already found the sum of the entire list. Otherwise, you look at the first item of the rest of the list, and ask the following question:
Is that item the same DU case as the sum so far?
If the answer is yes, then you add its value to the sum so far, and keep going through the loop. If the answer is no, then you make the "sum so far" value a None value instead of Some (case). So really, the "is it the same as the sum so far" question is actually two questions:
Is the "sum so far" a real value? (I.e., not None)?
Is the item I'm looking at the same DU case as the sum so far?
If the answer to both of these questions is "yes", then you add up the two values to get a new "sum so far" value. If it's "no", then you just set the "sum so far" to None, and your eventual result will be None as well.
Translating that approach into code looks like this:
let addToSum sumSoFar nextItem =
match sumSoFar with
| None -> None // Short-circuit if we previously found a mismatch
| Some x ->
match x, nextItem with
| Case1 a, Case1 b -> Some (Case1 (a + b))
| Case2 a, Case2 b -> Some (Case2 (a + b))
// ...
| CaseN a, CaseN b -> Some (CaseN (a + b))
| _ -> None // Mismatch
Now you need a function to apply a "combining" operation like that to the whole list. (A "combining" operation is any operation that takes two items of the same type and produces a single item of that same type; addition is one such operation, but so is multiplication, and a bunch of other things). There are two basic "apply this combining operation to the whole list" functions in F#, reduce and fold. The difference is that reduce takes the first item of the list as the initial "sum so far" value, and cannot work on an empty list. Whereas fold requires you to supply the initial value of its "sum so far" accumulator, but it can work on an empty list (for an empty list, the result of fold will simply be the initial "sum so far" value that you provided). In your case, since you don't initially know the type that your "sum so far" value should hold, you have to use reduce. So I'd suggest something like this:
let sumMyList values =
values |> List.choose id |> List.reduce addToSum
Except that List.reduce can't handle an empty list, and if the list you have is entirely None cases, that would blow up. (Can you see why?) So I'll add one more step to it, to handle empty lists:
let reduceSafely filteredValues =
match filteredValues with
| [] -> None
| _ -> filteredValues |> List.reduce addToSum
let sumMyList values =
values |> List.choose id |> reduceSafely
That should get you what you're looking for. And hopefully it's also given you insight into the process of designing a functional solution to your problems.
P.S. I recommend the F# track at http://exercism.io/ if you want more practice in figuring out the functional approach to problem-solving. I learned a lot running through those exercises!

F# on List of Elements

I am trying to write a F# function that finds the biggest value. I am new to F# and am confused as to how to implement this with the correct type and recursion.
Any help would be greatly appreciated along with an explanation of how it works, I really need to understand how it works so I can attempt to create other F# functions. Thanks!
When creating recursive functions, start thinking about the corner cases. Your helper function takes a list and a "maximum so far". Corner cases: What if your list is empty? What if you only have a 1 element list, or focus on the first element? That directly translates into a match statement:
let rec helper (l, m) =
match l, m with
| [], m -> m
| (l1 :: rest), m ->
let max1 = if l1 > m then l1 else m
helper(rest, max1)
I'll leave the wrapper findMax open, but clearly you can solve that using the same thinking: What if you get an empty list? (scream!) What if you get a list with elements (the first element is your maximum so far, feed the rest of the list into your helper)
And of course you could put it all into one function. I've chosen this rather roundabout helper because your template code was shaped in that way.
The first thing to do is to start thinking recursively and/or mathematically. In most general vague terms, it should look like "The result of my function is..." - then try to actually put into words what the result should be.
Applying to your particular problem, I would phrase it like this:
when given a list of one element, the result of findMax is that element.
when given a list of more than one element, the result of findMax is the maximum of the lists's head and the maximum element of its tail.
This thinking can be translated into F# almost word for word:
let rec findMax list =
match list with
| [x] -> x
| head::tail -> max head (findMax tail)
where:
let max a b = if a > b then a else b
Note, however, that this function is incomplete: it doesn't specify what the result should be when given an empty list. I will leave this as an exercise for the reader.

Flattening a tuple in Erlang

I am trying to turn a tuple of the form:
{{A,B,{C,A,{neg,A}}},{A,B,{neg,A}}}
Into
{{A,B,C,A,{neg,A}},{A,B,{neg,A}}
I'm quite new to Erlang so I would appreciate any hints. It makes no difference if the final structure is a list or a tuple, as long as any letter preceded by neg stays as a tuple/list.
A simple solution:
convert({{A,B,{C,D,E}},F}) -> {{A,B,C,D,E},F}.
If why this works is puzzling, consider:
1> YourTuple = {{a, b, {c, a, {neg, a}}}, {a, b, {neg, a}}}.
{{a,b,{c,a,{neg,a}}},{a,b,{neg,a}}}
2> Convert = fun({{A,B,{C,D,E}},F}) -> {{A,B,C,D,E},F} end.
#Fun<erl_eval.6.54118792>
3> Convert(YourTuple).
{{a,b,c,a,{neg,a}},{a,b,{neg,a}}}
The reason this happens is because we are matching over entire values based on the shape of the data. That's the whole point of matching, and also why its super useful in so many cases (and also why we want to use tuples in more specific circumstances in a language with matching VS a language where "everything is an iterable"). We can substitute the details with anything and they will be matched and returned accordingly:
4> MyTuple = {{"foo", bar, {<<"baz">>, balls, {ugh, "HURR!"}}}, {"Fee", "fi", "fo", "fum"}}.
{{"foo",bar,{<<"baz">>,balls,{ugh,"HURR!"}}},
{"Fee","fi","fo","fum"}}
5> Convert(MyTuple).
{{"foo",bar,<<"baz">>,balls,{ugh,"HURR!"}},
{"Fee","fi","fo","fum"}}
Why did this work when the last element of the top-level pair was so different in shape than the first one? Because everything about that second element was bound to the symbol F in the function represented by Convert (note that in the shell I named an anonymous function for convenience, this would be exactly the same as using convert/1 that I wrote at the top of this answer). We don't care what that second element was -- in fact we don't want to have to care about the details of that. The freedom to selectively not care about the shape of a given element of data is one of the key abstractions we use in Erlang.
"But those were just atoms 'a', 'b', 'c' etc. I have different things in there!"
Just to make it look superficially like your example above (and reinforce what I was saying about not caring about exactly what we bound to a given variable):
6> A = 1.
1
7> B = 2.
2
8> C = 3.
3
9> AnotherTuple = {{A, B, {C, A, {neg, A}}}, {A, B, {neg, A}}}.
{{1,2,{3,1,{neg,1}}},{1,2,{neg,1}}}
10> Convert(AnotherTuple).
{{1,2,3,1,{neg,1}},{1,2,{neg,1}}}
Needing to do this is not usually optimal, though. Generally speaking the other parts of the program that are producing that data in the first place should be returning useful data types for you. If not you can certainly hide them behind a conversion function such as the one above (especially when you're dealing with APIs that are out of your control), but generally speaking the need for this is a code smell.
And moving on
The more general case of "needing to flatten a tuple" is a bit different.
Tuples are tuples because each location within it has a meaning. So you don't usually hear of people needing to "flatten a tuple" because that fundamentally changes the meaning of the data you are dealing with. If you have this problem, you should not be using tuples to begin with.
That said, we can convert a tuple to a list, and we can check the shape of a data element. With these two operations in hand we could write a procedure that moves through a tuplish structure, building a list out of whatever it finds inside as it goes. A naive implementation might look like this:
-module(tuplish).
-export([flatten/1]).
-spec flatten(list() | tuple()) -> list().
flatten(Thing) ->
lists:flatten(flatten(Thing, [])).
flatten(Thing, A) when is_tuple(Thing) ->
flatten(tuple_to_list(Thing), A);
flatten([], A) ->
lists:reverse(A);
flatten([H | T], A) when is_tuple(H) ->
flatten(T, [flatten(H) | A]);
flatten([H | T], A) when is_list(H) ->
flatten(T, [flatten(H) | A]);
flatten([H | T], A) ->
flatten(T, [H | A]).
Keep in mind that after several years of writing Erlang code I have never needed to actually do this. Remember: tuples mean something different than lists.
All that said, the problem you are facing is almost certainly handled better by using records.

Is there an existing pattern to generate a list of the applications of a function to every combination of the items in two lists?

I'm just getting into functional programming and i'm in the "try out some non-trivial examples and ask others if I'm doing it wrong" phase. I'm following Don Syme's F# Tutorial and have decided to take a stab at the blackjack exercise at the end of Part II with a twist: he suggests treating Ace as 11 for simplicity's sake, but I decided to ignore that recommendation.
The way I'm handling it is by giving each card rank a list of possible values and building up a list of possible hand values recursively thus:
let cardValues (Card(rank, _)) =
match rank with
| Ace -> [1; 11]
| King | Queen | Jack -> [10]
| Value(value) -> [value]
let rec handValues = function
| [] -> [0]
| card::cards ->
[
for handValue in handValues cards do
for cardValue in cardValues card do
yield handValue + cardValue
]
The handValues function is so similar in structure to a fold that I can't shake the feeling there's already some high order function I can use to accomplish this. Is there something I'm missing or is this pretty much the right direction?
It's worth mentioning as an aside that this
[
for handValue in handValues cards do
for cardValue in cardValues card do
yield handValue + cardValue
]
is a monadic bind; one could author a 'list' monad and then use computation expressions to write this as
listMonad {
let! handVal = handValues cards
let! cardVal = cardValues card
return hardVal + cardVal
}
The way you're doing things is perfectly fine. It's possible to express any recursive function on lists as a fold, but I don't think that you gain anything by doing so here. There's also no built-in function to do exactly what you need, but you could build a more generic function and build your specific calculation on top of that. Here's one such approach:
let rec allChoices = function
| [] -> [[]]
| l::ls ->
[for x in l do
for xs in allChoices ls do
yield x::xs]
let values hand =
hand |>
List.map cardValues |>
allChoices |>
List.map (List.sum)
The allChoices function takes a list of lists and returns each possible list containing a single element from each (e.g. allChoices [[1];[2;3];[4;5]] = [[1;2;4];[1;2;5];[1;3;4];[1;3;5]]). We use this function to get all possible lists of values for the cards in a hand, and then sum each such list.
There are probably several other ways you could look at the problem which might suggest other variations.
I think your solution is already good.
Fold does not work in your case. We can fold a list of number, we can also fold two list of numbers. But in your case, it is not simply two lists of numbers.
Consider an extreme case that the your list contains all Aces with length n, then there are 2^n possible values. To enumerate all possibilities, you need a dfs search or bfs search. Your code is actually equivalent to a bfs search (so it costs more memory), although it writes in a recursive way.

Resources