Converting List (Maybe a) to Maybe (List a) in Elm - algorithm

What's a good way to convert List (Maybe a) to Maybe (List a) in Elm?
The logic is simple:
return Just (List a) if all items are Just a
otherwise, return Nothing.
Example 1:
input: [ Just 1, Just 2, Just 3 ]
output: Just [ 1, 2, 3 ]
Example 2:
input: [ Just 1, Nothing, Just 3 ]
output: Nothing
Can it be done easily with some of the built-in functions?
The best I came up with looks like this:
listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList listOfMaybes =
List.foldl
(\maybeItem ->
\maybeResultList ->
case ( maybeItem, maybeResultList ) of
( Just item, Just resultList ) ->
Just (List.append resultList [ item ])
( _, _ ) ->
Nothing
)
(Just [])
listOfMaybes
And what would be an appropriate name for this kind of function? As I was searching for an answer, I saw that there's a function called sequence in Haskell which seems to be doing something similar.

You can use the Elm Fancy Search tool and search on the function signature: List (Maybe a) -> Maybe (List a)
The first result turns up Maybe.Extra.combine

#Chad Gilbert's answer sure is correct, but if you're looking for a simpler implementation of such a function, then the following line will do the trick:
listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList listOfMaybes =
List.foldr (Maybe.map2 (::)) (Just []) listOfMaybes
Or just:
listOfMaybesToMaybeList : List (Maybe a) -> Maybe (List a)
listOfMaybesToMaybeList = List.foldr (Maybe.map2 (::)) (Just [])
Maybe.map2 just takes a function and two Maybe values and applies the function to the values:
> Maybe.map2 (+) (Just 2) (Just 3)
Just 5 : Maybe.Maybe number
> Maybe.map2 (::) (Just 2) (Just [1])
Just [2,1] : Maybe.Maybe (List number)
Note, that (::) function (prepend to the list) is used instead of (++) or List.append because it's more performant for the lists. Then foldr must be used instead of foldl to retain the order.

Related

How to write functions of functions in Scheme

I am supposed to write a function called (nth-filtered f n), where f is a function of one variable and n is a natural number, which evaluates to the nth natural number such that f applied to that number is #t.
If we called
(nth-filtered even? 1) we would get 2
(nth-filtered prime? 10) we would get 29
How do I make it so that it works for any sequential function? What should I think about when approaching this type of problem?
A variable is a variable and + is also a variable. The main difference between a function and some other data type is that you can wrap a function name in parentheses with arguments and it will become a new value.
eg.
(define (double fun)
(lambda (value)
(fun (fun value))))
(define (add1 v)
(+ 1 v))
(define add2 (double add1))
(add2 1) ; ==> 3
Now the contract doesn't say so you deduct by looking that you do (fun ...) that fun needs to be a function. Imagine this:
(define test (double 5)) ; probably works OK
(test 1)
The last one fails since you get application: 5 is not a procedure or something similar. The error message is not standardized.
How to attack your task is by making a helper that has the same arguments as your function but in addition the current number that I guess starts at 1. As I demonstrated you use the function variable as a function and recurse by always increasing the number and reducing n when the f call was #t. The actual function will just use the helper by passing all the parameters in addition to your state variable.
Your problem requires a fold, which is the standard way to iterate other a list while keeping a record of things done so far.
Here a very rackety method using for/fold:
(define (nth-filtered predicate index)
(for/fold ([count 0]
[current #f] #:result current)
([n (in-naturals 1)]) ; we start at 1 but we could start at 0
#:break (= count index)
(values (if (predicate n) (add1 count) count)
n)))
for/fold takes a list of initial state. Here we define count as the number of times the given predicate returned #t and current as the currently tested value.
Then it takes a list of iterators, in this case we only iterate infinitely over (in-naturals).
To make it stop, we provide a #:break condition, which is "when the number of truthy predicates (count) is equal to the requested amount (index)".
for/fold requests that it's body finishes with a list of values for each "state" variable, in order to update them for the next iteration. Here we provide two values: one is the new count, the other is just the current n.
You can try it out, it works as you requested:
> (nth-filtered even? 1)
2
> (require math/number-theory)
> (nth-filtered prime? 10)
29
> (nth-filtered prime? 5)
11

Standard ML polymorphic sorting

I am very inexperienced in ML, and I just can't make sense of this.
Start question
Polymorphic Sorting
This function performing insertion sort on a list takes as arguments a comparison function less and a list l of elements to be sorted. The code compiles and runs correctly:
fun sort(less, nil) = nil |
sort(less, a : : l) =
let
fun insert(a, nil) = a : : nil |
insert(a, b : : l) = if less(a,b) then a : : (b: : l)
else b : : insert(a, l)
in
insert(a, sort(less, l))
end;
What is the type of this sort function? Explain briefly, including the type of the subsidiary function insert. You do not have to run the ML algorithm on this code; just explain why an ordinary ML programmer would expect the code to have this type. (End of question)
I've gotten the type of the sort function (by running the code in an SML interpreter), but I just can't get the second part about insert.
Type of sort function:
val sort = fn : ('a * 'a -> bool) * 'a list -> 'a list
Any help would be greatly appreciated.
That you figured out the type of sort by "cheating" makes the next step harder; don't take shortcuts.
(Nobody ever learned anything by peeking at the answer.)
But here's how you could figure out insert:
You know from
val sort = fn : ('a * 'a -> bool) * 'a list -> 'a list
that the second argument to sort is an 'a list.
In
insert(a, sort(less, l))
you can see immediately that it has some type (X * Y) -> Z for some X, Y, and Z.
You're passing the first element of sort's second argument - a - as insert's first argument.
Since sort's second argument is an 'a list, that list's first element is an 'a.
So X is 'a, and we now know that insert is ('a * Y) -> Z for some Y and Z.
The type of insert's second argument - sort(less, l) - is well known; it's 'a list.
So we now know that Y is 'a list, and insert is ('a * 'a list) -> Z for some Z.
All that remains is the return type, and since
insert(a, sort(less, l))
is what sort returns, it must have the same return type as sort.
So Z is 'a list.
In summary, insert's type is
('a * 'a list) -> 'a list

relation between foldr and append in Scheme

try to figure out how to use "append" in Scheme
the concept of append that I can find like this:
----- part 1: understanding the concept of append in Scheme-----
1) append takes two or more lists and constructs a new list with all of their elements.
2) append requires that its arguments are lists, and makes a list whose elements are the elements of those lists. it concatenates the lists it is given. (It effectively conses the elements of the other lists onto the last list to create the result list.)
3) It only concatenates the top-level structure ==> [Q1] what does it mean "only concatenates the top-level"?
4) however--it doesn't "flatten" nested structures.
==> [Q2] what is "flatten" ? (I saw many places this "flatten" but I didn't figure out yet)
==> [Q3] why append does not "flatten" nested structures.
---------- Part 2: how to using append in Scheme --------------------------------
then I looked around to try to use "append" and I saw other discussion
based on the other discussion, I try this implementation
[code 1]
(define (tst-foldr-append lst)
(foldr
(lambda (element acc) (append acc (list element)))
lst
'())
)
it works, but I am struggling to understand that this part ...(append acc (list element)...
what exactly "append" is doing in code 1, to me, it just flipping.
then why it can't be used other logics e.g.
i) simply just flip or
iii).... cons (acc element).....
[Q4] why it have to be "append" in code 1??? Is that because of something to do with foldr ??
again, sorry for the long question, but I think it is all related.
Q1/2/3: What is this "flattening" thing?
Scheme/Lisp/Racket make it very very easy to use lists. Lists are easy to construct and easy to operate on. As a result, they are often nested. So, for instance
`(a b 34)
denotes a list of three elements: two symbols and a number. However,
`(a (b c) 34)
denotes a list of three elements: a symbol, a list, and a number.
The word "flatten" is used to refer to the operation that turns
`(3 ((b) c) (d (e f)))
into
`(3 b c d e f)
That is, the lists-within-lists are "flattened".
The 'append' function does not flatten lists; it just combines them. So, for instance,
(append `(3 (b c) d) `(a (9)))
would produce
`(3 (b c) d a (9))
Another way of saying it is this: if you apply 'append' to a list of length 3 and a list of length 2, the result will be of length 5.
Q4/5: Foldl really has nothing to do with append. I think I would ask a separate question about foldl if I were you.
Final advice: go check out htdp.org .
Q1: It means that sublists are not recursively appended, only the top-most elements are concatenated, for example:
(append '((1) (2)) '((3) (4)))
=> '((1) (2) (3) (4))
Q2: Related to the previous question, flattening a list gets rid of the sublists:
(flatten '((1) (2) (3) (4)))
=> '(1 2 3 4)
Q3: By design, because append only concatenates two lists, for flattening nested structures use flatten.
Q4: Please read the documentation before asking this kind of questions. append is simply a different procedure, not necessarily related to foldr, but they can be used together; it concatenates a list with an element (if the "element" is a list the result will be a proper list). cons just sticks together two things, no matter their type whereas append always returns a list (proper or improper) as output. For example, for appending one element at the end you can do this:
(append '(1 2) '(3))
=> '(1 2 3)
But these expressions will give different results (tested in Racket):
(append '(1 2) 3)
=> '(1 2 . 3)
(cons '(1 2) '(3))
=> '((1 2) 3)
(cons '(1 2) 3)
=> '((1 2) . 3)
Q5: No, cons will work fine here. You wouldn't be asking any of this if you simply tested each procedure to see how they work. Please understand what you're using by reading the documentation and writing little examples, it's the only way you'll ever learn how to program.

Simple Typed Racket program doesn't type-check

I'm a rank beginner with Typed Racket, and I was playing around with the very simple Tree type defined in the Beginner's Guide:
#lang typed/racket
(define-type Tree (U leaf node))
(struct: leaf ([val : Number]))
(struct: node ([left : Tree] [right : Tree]))
As an exercise, I decided to write a higher-order function to descend the tree:
(: tree-descend : All (A) (Number -> A) (A A -> A) Tree -> A)
(define (tree-descend do-leaf do-node tree)
(if (leaf? tree)
(do-leaf (leaf-val tree))
(do-node (tree-descend do-leaf do-node (node-left tree))
(tree-descend do-leaf do-node (node-right tree)))))
This type-checks fine. However, when I try to use it to redefine the tree-sum function that sums all over the leaves, I get a surprising and verbose error message:
(: tree-sum : Tree -> Number)
(define (tree-sum t)
(tree-descend identity + t))
The error messages are
Type Checker: Polymorphic function `tree-descend' could not be applied to arguments:
Argument 1:
Expected: (Number -> A)
Given: (All (a) (a -> a))
Argument 2:
Expected: (A A -> A)
Given: (case-> (-> Zero) (Zero Zero -> Zero) (One Zero -> One)
(Zero One -> One) (Positive-Byte Zero -> Positive-Byte)
[...lots of ways of combining subtypes of Number...]
(Index Positive-Index Index -> Positive-Fixnum)
(Index Index Positive-Index -> in: (tree-descend identity + t)
Now, to my untrained eye, it looks like this should work just fine, because clearly the polymorphic type A should just be Number and then everything works. Obviously the language disagrees with me for some reason, but I'm not sure what that reason is.
Unfortunately, Typed Racket can't infer the proper instantiation of polymorphic functions like tree-descend when you apply them to polymorphic arguments like identity. If you replace identity with (inst identity Number), then the program works fine.

How does `for` work in this recursive Clojure code?

Clojure beginner here. Here's some code I'm trying to understand, from http://iloveponies.github.io/120-hour-epic-sax-marathon/sudoku.html (one page of a rather nice beginning Clojure course):
Subset sum is a classic problem. Here’s how it goes. You are given:
a set of numbers, like #{1 2 10 5 7}
and a number, say 23
and you want to know if there is some subset of the original set that sums up to the target.
We’re going to solve this by brute force using a backtracking search.
Here’s one way to implement it:
(defn sum [a-seq]
(reduce + a-seq))
(defn subset-sum-helper [a-set current-set target]
(if (= (sum current-set) target)
[current-set]
(let [remaining (clojure.set/difference a-set current-set)]
(for [elem remaining
solution (subset-sum-helper a-set
(conj current-set elem)
target)]
solution))))
(defn subset-sum [a-set target]
(subset-sum-helper a-set #{} target))
So the main thing happens inside subset-sum-helper. First of all, always check if we have found
a valid solution. Here it’s checked with
(if (= (sum current-set) target)
[current-set]
If we have found a valid solution, return it in a vector (We’ll see soon why in a vector). Okay,
so if we’re not done yet, what are our options? Well, we need to try adding some element of
a-set into current-set and try again. What are the possible elements for this? They are those
that are not yet in current-set. Those are bound to the name remaining here:
(let [remaining (clojure.set/difference a-set current-set)]
What’s left is to actually try calling subset-sum-helper with each new set obtainable
in this way:
(for [elem remaining
solution (subset-sum-helper a-set
(conj current-set elem)
target)]
solution))))
Here first elem gets bound to the elements of remaining one at a time. For each elem,
solution gets bound to each element of the recursive call
solution (subset-sum-helper a-set
(conj current-set elem)
target)]
And this is the reason we returned a vector in the base case, so that we can use for
in this way.
And sure enough, (subset-sum #{1 2 3 4} 4) returns (#{1 3} #{1 3} #{4}).
But why must line 3 of subset-sum-helper return [current-set]? Wouldn't that return a final answer of ([#{1 3}] [#{1 3}] [#{4}])?
I try removing the enclosing brackets in line 3, making the function begin like this:
(defn subset-sum-helper [a-set current-set target]
(if (= (sum current-set) target)
current-set
(let ...
Now (subset-sum #{1 2 3 4} 4) returns (1 3 1 3 4), which makes it look like let accumulates not the three sets #{1 3}, #{1 3}, and #{4}, but rather just the "bare" numbers, giving (1 3 1 3 4).
So subset-sum-helper is using the list comprehension for within a recursive calculation, and I don't understand what's happening. When I try visualizing this recursive calculation, I found myself asking, "So what happens when
(subset-sum-helper a-set
(conj current-set elem)
target)
doesn't return an answer because no answer is possible given its starting point?" (My best guess is that it returns [] or something similar.) I don't understand what the tutorial writer meant when he wrote, "And this is the reason we returned a vector in the base case, so that we can use for in this way."
I would greatly appreciate any help you could give me. Thanks!
The subset-sum-helper function always returns a sequence of solutions. When the target is not met, the solution body at the end of the for expression enumerates such a sequence. When target is met, there is only one solution to return: the current-set argument. It must be returned as a sequence of one element. There are many ways to do this:
[current-set] ; as given - simplest
(list current-set)
(cons current-set ())
(conj () current-set)
...
If you cause an immediate return from subset-sum-helper (no recursion), you'll see the vector:
=> (subset-sum #{} 0)
[#{}]
Otherwise you'll see a sequence generated by for, which prints like a list:
=> (subset-sum (set (range 1 10)) 7)
(#{1 2 4}
#{1 2 4}
#{1 6}
#{1 2 4}
#{1 2 4}
#{2 5}
#{3 4}
#{1 2 4}
#{1 2 4}
#{3 4}
#{2 5}
#{1 6}
#{7})
When no answer is possible, subset-sum-helper returns an empty sequence:
=> (subset-sum-helper #{2 4 6} #{} 19)
()
Once again, this is printed as though it were a list.
The algorithm has problems:
It finds each solution many times - factorial of (count s) times for a solution s.
If an adopted element elem overshoots the target, it
uselessly tries adding every permutation of the remaining set.
The code is easier to understand if we recast it somewhat.
The recursive call of subset-sum-helper passes the first and third arguments intact. If we use letfn to make this function local to subset-sum, we can do without these arguments: they are picked up from the context. It now looks like this:
(defn subset-sum [a-set target]
(letfn [(subset-sum-helper [current-set]
(if (= (reduce + current-set) target)
[current-set]
(let [remaining (clojure.set/difference a-set current-set)]
(for [elem remaining
solution (subset-sum-helper (conj current-set elem))]
solution))))]
(subset-sum-helper #{})))
... where the single call to the sum function has been expanded inline.
It is now fairly clear that subset-sum-helper is returning the solutions that include its single current-set argument. The for expression is enumerating, for each element elem of a-set not in the current-set, the solutions containing the current set and the element. And it is doing this in succession for all such elements. So, starting with the empty set, which all solutions contain, it generates all of them.
Maybe this explanation helps you:
Firstly we can experiment in a minimal code the expected behaviour (with and without brackets) of the for function but removing the recursion related code
With brackets:
(for [x #{1 2 3}
y [#{x}]]
y)
=> (#{1} #{2} #{3})
Without brackets:
(for [x #{1 2 3}
y #{x}]
y)
=> (1 2 3)
With brackets and more elements into the brackets*:**
(for [x #{1 2 3}
y [#{x} :a :b :c]]
y)
=> (#{1} :a :b :c #{2} :a :b :c #{3} :a :b :c)
So you need (on this case) the brackets to avoid iterating over the set.
If we dont use the brackets we'll have "x" as binding value for y, and if we use the brackets we'll have #{x} as binding value for y.
In other words the code author needs a set and not iterating over a set as a binding value inside its for. So she put a set into a sequence "[#{x}]"
And summarising
"for" function takes a vector of one or more binding-form/collection-expr pairs
So if your "collection-expre" is #{:a} the iteration result will be (:a) but if your "collection-expre" is [#{:a}] the iteration result will be (#{:a})
Sorry for the redundance on my explanations but it's difficult to be clear with these nuances
Just for fun, here's a cleaner solution, still using for:
(defn subset-sum [s target]
(cond
(neg? target) ()
(zero? target) (list #{})
(empty? s) ()
:else (let [f (first s), ns (next s)]
(lazy-cat
(for [xs (subset-sum ns (- target f))] (conj xs f))
(subset-sum ns target)))))

Resources