Related
If I have this code:
fun coord_select (x : int, cs : (int*int) list) =
List.filter (fn (first, _) => first = x ) cs
testing with input gives this:
coord_select (2, [(2,2),(2,3),(3,3),(4,3)])
: val it = [(2,2),(2,3)] : (int * int) list
Now, what if I don't give the desired first coordinate as an int but as a list of several required first coordinates such as [3,4], i.e., I want all coordinate tuples that start with 3 as well as 4? The easy way would simply to create a recursive wrapper around this that went through the list and plugged in the value as coord_select's first variable. But I would like to understand nested things better than such brute force. So I came up with this:
fun coord_match (fs : int list, cs :(int*int) list) =
map (coord_select (f, cs)) fs
but this can't really work because, as was pointed out, coord_select in the map is actually trying to return a list -- and how does map know to plug in the members of fs into f in the first place? Common Lisp does have a device to keep functions like this from running, i.e., the ' operator. But this wouldn't help, again, because map doesn't know which variable fs is supplying. For input, e.g., I have these coordinates:
[(2,2),(2,3),(3,3),(4,3)]
and I have this list of x-coordinates to match against the above list
[3,4]
Again, I could just put a recursive wrapper around this, but I'm reaching for a more elegant nested solution from the greater fold family.
what if I don't give the desired first coordinate as an int but as a list of several required first coordinates such as [3,4], i.e., I want all coordinate tuples that start with 3 and 4
It sounds like you want all coordinate tuples that start with 3 or 4, since a coordinate can't both be 3 and 4.
Given that, you can write coord_select like:
fun member (x, xs) =
List.exists (fn x2 => x = x2) xs
fun coord_select (xs, coords) =
List.filter (fn (x, _) => member (x, xs)) coords
the greater fold family
This family is called catamorphisms, of which map, filter, exists and foldl belong. Since foldl is the most general of these, it is technically possible to write the code above using folds entirely:
fun coord_select (xs, coords) =
foldr (fn ((x, y), acc1) =>
if foldl (fn (x2, acc2) => acc2 orelse x = x2) false xs
then (x, y) :: acc1
else acc1) [] coords
but as should be evident, explicit folds are not very readable.
If there's a specialised combinator that does a job, you would rather want that over a fold. And if it doesn't exist, creating it from slightly less specialised combinators improves readability. Folding is as close to manual recursion as you get and so provides little information to the reader about what kind of recursion we're attempting.
For that reason I also made member from exists, since exists requires me to specify a predicate and my predicate is "equality with x"; so even exists, I feel, adds clutter to the coord_select function.
You can learn more about list catamorphisms in functional programming by reading Functional Programming with Bananas, Lenses, Envelopes and Barbed Wire (1991) by Meijer, Fokkinga, Paterson.
I just started learning Prolog this week so I am not sure if for-loops are possible in Prolog.
I have two lists in Prolog
stringList([hi,hello],[bye,later],X).
How do I create a new solution list with one element per list?
So the output should be:
X = [hi,bye]
X = [hi,later]
X = [hello,bye]
X = [hello,later]
A major advantage when using Prolog is that you can delegate such loops to the Prolog engine. You do not have to write them explicitly.
For example, in your case, think about the problem in this way: What holds (or should hold) about X?
We can say:
X is a list with two elements, say [A,B].
A is a member of the list that is denoted by the first argument.
B is a member of the list that is denoted by the second argument.
So, in Prolog:
one_from_each(As, Bs, [A,B]) :-
member(A, As),
member(B, Bs).
Sample query:
?- one_from_each([hi,hello],[bye,later], X).
X = [hi, bye] ;
X = [hi, later] ;
X = [hello, bye] ;
X = [hello, later].
And it works in other directions too:
?- one_from_each(As, Bs, [hi,bye]).
As = [hi|_4656],
Bs = [bye|_4662] ;
As = [hi|_4656],
Bs = [_4660, bye|_4668] ;
As = [hi|_4656],
Bs = [_4660, _4666, bye|_4674] .
Hence, the whole question is somewhat misguided. When coding in Prolog, always ask: How can I formulate what ought to hold? Once you have such a formulation, you can leave the search for solutions to the Prolog engine!
If you want, you can be more explicit. For example:
one_from_each([], _) --> [].
one_from_each([L|Ls], Rs) -->
one_from_each_(Rs, L),
one_from_each(Ls, Rs).
one_from_each_([], _) --> [].
one_from_each_([R|Rs], L) -->
[[L,R]],
one_from_each_(Rs, L).
Example:
?- phrase(one_from_each([hi,hello],[bye,later]), Ls).
Ls = [[hi, bye], [hi, later], [hello, bye], [hello, later]].
This is sometimes called a spatial representation, because the solutions are now no longer found on backtracking (temporal representation), but represented explicitly.
From this, you see that "loops" correspond to recursive definitions.
I am very new to SML and i am trying to write a function where it compares two char lists, in a way that it takes one character from list1 and compares it with all the characters from list2, for example
val list1 = explode("abcdefghijklmnopqrstuvwxyz")
val list2 = explode("bcdaghklfeijonmtrqpsvuwyzx!-232=,./;'[]{}:?<")
so from list1 it takes the element 'a', and then compares it with each element of list2 and it keeps checking all elements, if the jumbled list2 is equal to to the non jumbled list1 then it returns true
This sounds like an XY problem,
The XY problem is asking about your attempted solution rather than your actual problem. This leads to enormous amounts of wasted time and energy, both on the part of people asking for help, and on the part of those providing help.
Are you testing if list1 is a subset, sub-multiset, sub-string, sub-sequence, or a permutation of list2? Or if they are set-equivalent? Try and express your actual problem and then describe your attempted solution. :-)
You probably want to use a combination of List.exists and List.all.
For example, if you were to test if list1 is a subset of list2:
fun contains (ys, x) = List.exists (fn y => x = y) ys
fun isSubsetOf (xs, ys) = List.all (fn x => contains (ys, x)) xs
Which says: For all x ∈ xs, there must exist a y ∈ ys such that x = y.
I was trying to do a simulation of the Rubik's cube in Elm when I noticed Elm doesn't support list comprehensions. In Haskell or even Python I would write something like:
ghci> [2*c | c <- [1,2,3,4]]
[2,4,6,8]
I could not find a way in Elm. The actual list comprehension I had to write was (in Haskell):
ghci> let x = [0,1,3,2]
ghci> let y = [2,3,1,0]
ghci> [y !! fromIntegral c | c <- x]
[2,3,0,1]
where fromIntegral :: (Integral a, Num b) => a -> b turns Integer into Num.
In Elm, I tried to use Arrays:
x = Array.fromList [0,1,3,2]
y = Array.fromList [2,3,1,0]
Array.get (Array.get 2 x) y
And I started getting difficulties with Maybe types:
Expected Type: Maybe number
Actual Type: Int
In fact, I had to look up what they were. Instead of working around the maybe, I just did something with lists:
x = [0,1,3,2]
y = [2,3,1,0]
f n = head ( drop n x)
map f y
I have no idea if that's efficient or correct, but it worked in the cases I tried.
I guess my two main questions are:
does Elm support list comprehensions? ( I guess just use map)
how to get around the maybe types in the Array example?
is it efficient to call head ( drop n x) to get the nth element of a list?
Elm doesn't and will not support list comprehensions: https://github.com/elm-lang/Elm/issues/147
The style guide Evan refers to says 'prefer map, filter, and fold', so.. using `map:
map ((y !!).fromIntegral) x
or
map (\i-> y !! fromIntegral i) x
Commenters point out that (!!) isn't valid Elm (it is valid Haskell). We can define it as either:
(!!) a n = head (drop n a), a total function.
or perhaps
(!!) a n = case (head (drop n a)) of
Just x -> x
Nothing -> crash "(!!) index error"
I don't know much about Elm, so I can't answer to whether it supports list comprehensions (couldn't find anything via Google about it either way), but I can answer your other two questions.
How to get around the Maybe types in the Array example?
The type of Array.get is Int -> Array a -> Maybe a, which means that it returns either Nothing or Just x, where x is the value at the given index. If you want to feed the result of one of these operations into another, in Haskell you could just do
Array.get 2 x >>= \i -> Array.get i y
Or with do notation:
do
i <- Array.get 2 x
Array.get i y
However, from a quick search it seems that Elm may or may not support all monadic types, but hopefully you can still use a case statement to get around this (it's just not very fun)
case Array.get 2 x of
Nothing -> Nothing
Just i -> Array.get i y
In fact, I would recommend writing a function to do this in general for you, it's just a direct clone of >>= for Maybe in Haskell:
mayBind :: Maybe a -> (a -> Maybe b) -> Maybe b
mayBind Nothing _ = Nothing
mayBind (Just x) f = f x
Then you could use it as
Array.get 2 x `mayBind` (\i -> Array.get i y)
Is it efficient to call head (drop n x) to get the nth element of a list?
No, but neither is direct indexing, which is equivalent to head . drop n. For lists, indexing will always be O(n) complexity, meaning it takes n steps to get the nth element from the list. Arrays have a different structure, which lets them index in logarithmic time, which is significantly faster. For small lists (< 100 elements), this doesn't really matter, but once you start getting more than a hundred or a thousand elements, it starts becoming a bottleneck. Lists are great for simple code that doesn't have to be the fastest, as they are generally more convenient. Now, I don't know how exactly this gets translated in Elm, it may be that Elm will convert them into Javascript arrays, which are true arrays and indexable in O(1) time. If Elm uses its own version of Haskell lists after it's been compiled, then you'll still have a slowdown.
Haskell
addm::[Int]->Int
addm (x:xs) = sum(x:xs)
I was able to achieve to get a sum of a list using sum function but is it possible to get the sum of a list using map function? Also what the use of map function?
You can't really use map to sum up a list, because map treats each list element independently from the others. You can use map for example to increment each value in a list like in
map (+1) [1,2,3,4] -- gives [2,3,4,5]
Another way to implement your addm would be to use foldl:
addm' = foldl (+) 0
Here it is, the supposedly impossible definition of sum in terms of map:
sum' xs = let { ys = 0 : map (\(a,b) -> a + b) (zip xs ys) } in last ys
this actually shows how scanl can be implemented in terms of map (and zip and last), the above being equivalent to foldl (+) 0 xs === last $ scanl (+) 0 xs:
scanl' f z xs = let { ys = z : map (uncurry f) (zip ys xs) } in ys
I expect one can calculate many things with map, arranging for all kinds of information flow through zip.
edit: the above is just a zipWith in disguise of course (and zipWith is kind of a map2):
sum' xs = let { ys = 0 : zipWith (+) ys xs } in last ys
This seems to suggest that scanl is more versatile than foldl.
It is not possible to use map to reduce a list to its sum. That recursive pattern is a fold.
sum :: [Int] -> Int
sum = foldr (+) 0
As an aside, note that you can define map as a fold as well:
map :: (a -> b) -> ([a] -> [b])
map f = fold (\x xs -> f x : xs) []
This is because foldr is the canonical recursive function on lists.
References: A tutorial on the universality and expressiveness of fold, Graham Hutton, J. Functional Programming 9 (4): 355–372, July 1999.
After some insights I have to add another answer: You can't get the sum of a list with map, but you can get the sum with its monadic version mapM. All you need to do is to use a Writer monad (see LYAHFGG) over the Sum monoid (see LYAHFGG).
I wrote a specialized version, which is probably easier to understand:
data Adder a = Adder a Int
instance Monad Adder where
return x = Adder x 0
(Adder x s) >>= f = let Adder x' s' = f x
in Adder x' (s + s')
toAdder x = Adder x x
sum' xs = let Adder _ s = mapM toAdder xs in s
main = print $ sum' [1..100]
--5050
Adder is just a wrapper around some type which also keeps a "running sum." We can make Adder a monad, and here it does some work: When the operation >>= (a.k.a. "bind") is executed, it returns the new result and the value of the running sum of that result plus the original running sum. The toAdder function takes an Int and creates an Adder that holds that argument both as wrapped value and as running sum (actually we're not interested in the value, but only in the sum part). Then in sum' mapM can do its magic: While it works similar to map for the values embedded in the monad, it executes "monadic" functions like toAdder, and chains these calls (it uses sequence to do this). At this point, we get through the "backdoor" of our monad the interaction between list elements that the standard map is missing.
Map "maps" each element of your list to an element in your output:
let f(x) = x*x
map f [1,2,3]
This will return a list of the squares.
To sum all elements in a list, use fold:
foldl (+) 0 [1,2,3]
+ is the function you want to apply, and 0 is the initial value (0 for sum, 1 for product etc)
As the other answers point out, the "normal" way is to use one of the fold functions. However it is possible to write something pretty similar to a while loop in imperative languages:
sum' [] = 0
sum' xs = head $ until single loop xs where
single [_] = True
single _ = False
loop (x1 : x2 : xs) = (x1 + x2) : xs
It adds the first two elements of the list together until it ends up with a one-element list, and returns that value (using head).
I realize this question has been answered, but I wanted to add this thought...
listLen2 :: [a] -> Int
listLen2 = sum . map (const 1)
I believe it returns the constant 1 for each item in the list, and returns the sum!
Might not be the best coding practice, but it was an example my professor gave to us students that seems to relate to this question well.
map can never be the primary tool for summing the elements of a container, in much the same way that a screwdriver can never be the primary tool for watching a movie. But you can use a screwdriver to fix a movie projector. If you really want, you can write
import Data.Monoid
import Data.Foldable
mySum :: (Foldable f, Functor f, Num a)
=> f a -> a
mySum = getSum . fold . fmap Sum
Of course, this is silly. You can get a more general, and possibly more efficient, version:
mySum' :: (Foldable f, Num a) => f a -> a
mySum' = getSum . foldMap Sum
Or better, just use sum, because its actually made for the job.