Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
Can some sort of if statement be used inside list comprehension to determine one of several outcomes for each element of a list?
Say I have a list comprehension over a list that contains elements which are either a 0 or a 1.
If the value is a 0, then the string "off" needs to be stored in another list in the same position. If the value is 1 then "on".
This is just an example. It looks easily done with recursion, but what if this needs to be done on a list of lists? Or lists of lists of lists?
Yes, of course you can:
on_or_off_list xs = [if x == 0 then "off" else "on" | x <- xs]
Or in a more point-free style:
on_or_off 0 = "off"
on_or_off _ = "on"
on_or_off_list = map on_or_off
Yes, using mutually-exclusive tests in singleton lists with guards:
foo :: (Num a, Eq a) => [a] -> [String]
foo xs = [s | x <- xs, s <- ["off" | x==0] ++ ["on" | x==1]]
Or you could just use the if expression directly,
bar :: (Num a, Eq a) => [a] -> [String]
bar xs = [s | x <- xs, let s = if x==0 then "off" else "on"]
This answers your specific question.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 months ago.
Improve this question
I'm trying to learn functional programming with Ocaml and I want to implement a function, which returns the sum of the elements in a list. I want to do it using a while loop, but I can't think of a way to write the check.
I imagined something like this
let sum_it (xs: int list) =
let j = ref 1 in
let add x y = x+y in
while xs <> [] do
j := add !j hd ;
xs = tl done ;
!j ;;
but now it fails with the j := add !j hd ;
Error: This expression has type 'a list -> 'a
but an expression was expected of type int
The OCaml way to analyze the shape of a value is to use pattern matching:
match list with
| [] -> ... (* 1 *)
| a :: q -> ... (* 2 *)
Compared to a language with only conditionals (like C), the advantage of pattern matching is that it directly associate a check to see if a value has a certain shape with the action to run for values of that shape. Combined with the possibility to check if a pattern matching covers all case, this decrease considerably the room for mistakes.
For instance, with
| [] -> ... (* 1 *)
the action 1 on the right hand side of -> is only run if the matched list list is empty whereas the second action
| a :: q -> ... (* 2 *)
is only run if the list has the shape a :: q for some a and q. Moreover, this second action can use the value a of the head of the list and the value q of the tail of the list directly in its body. For instance
| a :: q -> a + List.length q
sums the first element of the list list with the length of its tail.
P.S: The use of while loop for simple recursive function is not optimal. The idiomatic OCaml way is to define a recursive function. Indeed, a while loop may have a very complex flow of data. Contrarily, a pure recursive function will have much more explicit and often simpler flow of data.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 1 year ago.
Improve this question
I have to implement a(n) [a -> b] -> [a] -> [b] function that has to run the given functions on the second list's respective elements.
For example:
functionList [\x->x+2] [2] == [4]
functionList [\x->x+2, \x->x-2, \x->x*2] [2,3,6] == [4,1,12]
So far, I have this:
functionList f xs = [ f x | x <- f ]
which returns a type matching error I don't know what to do with.
You can use zip :: [a] -> [b] -> [(a,b)] to simplify the problem. If you wanted to use it directly that'd probably look like a = (map (uncurry ($))) . zip, but zipWith is a normal shortcut that you should use.
Another option is to use ZipList (docs).
import Control.Applicative (ZipList(..))
-- I'm just writing this in the text box; i haven't checked if it parses.
a fs xs = getZipList $ ($) <$> (ZipList fs) <*> (ZipList xs)
ZipList is probably the worst (most verbose, without a clarity advantage) solution for this very simple situation.
Of course you could also re-implement zip by pattern matching on the lists' structures. I would not expect there to be any advantage to that, but if zip is new to you then you should take a minute to write out both versions, just for practice/understanding.
a [] _ = []
a _ [] = []
a (f:fs) (x:xs) = ...
A slight improvement over #ShapeOfMatter's excellent answer is:
import Control.Applicative (ZipList(..))
a :: [a -> b] -> [a] -> [b]
a fs xs = getZipList (ZipList fs <*> ZipList xs)
You can use parallel list comprehensions:
{-# LANGUAGE ParallelListComp #-}
functionList fs xs = [f x | f <- fs | x <- xs]
Do you want to have to ask for and get answers on stack overflow every time you have a problem to solve or do you want to learn how to write the code yourself? to be able to deal with the errors yourself? to learn how to fix them yourself? if so then start by including the error message in your questions. we could then show you how to use the errors as the guide to fixing your code. the point to learning Haskell is not to memorize its library functions, but to master the basics so that the code should practically write itself for you. and then you can memorize and use the library functions.
But even without the error message, isn't it clear from the examples that
functionList [\x->x+2] [2] == [4] == [(\x->x+2) 2]
and
functionList [\x->x+2, \x->x-2, \x->x*2] [2,3,6]
== [4,1,12]
== [(\x->x+2) 2, (\x->x-2) 3, (\x->x*2) 6]
? and then
functionList [\x->x-2, \x->x*2] [3,6]
== [1,12]
== [(\x->x-2) 3, (\x->x*2) 6]
and so
functionList [\x->x+2, \x->x-2, \x->x*2] [2,3,6]
== [(\x->x+2) 2] ++ [(\x->x-2) 3, (\x->x*2) 6]
== [(\x->x+2) 2] ++ functionList [\x->x-2, \x->x*2] [3,6]
? which is to say,
functionList (
(\x->x+2) : [\x->x-2, \x->x*2] )
( 2 : [3,6])
== ((\x->x+2) 2) : functionList [\x->x-2, \x->x*2] [3,6]
? and does all this really depend on the specific values used here or would it work with any functions f,g,h, ..., and their arguments -- any number of them?
So can it be generalized?
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have these exercises
Define a function to count the total negative numbers in a list. ##
I've tried this
negative :: [Int] -> Int
negative list = [ x | x <- list, if list<0 then x=1 else x=0]
And also
Define the function
choose :: Int -> [Int] -> [Int]
that chooses all occurrences of an integer n in a list. For example
chooses 1 [1, 2, 1, 4, 5, 1] results in [1, 1, 1] choosing 1 [2, 3, 4, 6] results []
I've tried this
choose :: Int->[Int]->[Int]
choose xs ys s [rep-rep<-xs,z<-ys,rep-z]
Or
rep ::Int->[Int]->[Int]
rep _ [][]
rep a (b:bs)-a-b-a:rep a []
|otherwise-rep a (bs)
rp :: [Int] -> [Int] -> [Int]
rp [] (ys)[]
rp (x:xs) (ys)-k++rp (xs) (ys)
where k'rep x (ys)
My teacher never explained this to us that's why I have these doubts, I'm new to haskell
The expression:
negative :: [Int] -> Int
negative list = [ x | x <- list, if list<0 then x=1 else x=0]
Makes no sense for several reasons:
the result type is an Int, so by using list comprehension as outer expression, you are generating a list;
x is an element of the list x <- list, if list < 0 then … else … makes no sense since list is a list, and can not be compared with a single element; and
variables can not be assigned a new value. Variables are defined once, here by x <- list. You can make a more locally scoped variable with the same name, but that is not a good idea here.
You can just use filter :: (a -> Bool) -> [a] -> [a] here to filter the list and only retain the elements less than 0 and then calculate the length :: Foldable f => f a -> Int:
negative :: [Int] -> Int
negative list = length (filter (< 0) list)
we can make these point-free, and let this work with any Num type:
negative :: (Num a, Ord a) => [a] -> Int
negative = length . filter (< 0)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I have this Map in Scala:
var m = Map(1 -> List("A","B","C","D"), 2 -> List("F","G","H","I"))
and I want to convert it on this:
var m = Map(1->"A", 1->"B", 1->"C", 1->"D", 2->"F",2->"G",2->"H",2->"I")
Any advice? Thanks in advance!!
This should give you what you want:
val map = Map(1 -> List("A","B","C","D"), 2 -> List("F","G","H","I"))
val result =
map.iterator.flatMap {
case (key, values) =>
values.map(value => key -> value)
}.toList
// result: List[(Int, String)] = List((1,A), (1,B), (1,C), (1,D), (2,F), (2,G), (2,H), (2,I))
Actually there is no solution because a map can not have repeated keys. The closest approach would be something like this:
m.map {case (k, v) => v.map((k,_))}.flatten
res215: scala.collection.immutable.Iterable[(Int, String)] = List((1,A), (1,B), (1,C), (1,D), (2,F), (2,G), (2,H), (2,I))
Thanks to all and sorry for the question.
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 4 years ago.
Improve this question
Need to implement a split with foldl or foldr.
For example: split [2, 4, 6, 8, 7] into ([2, 6, 7], [4, 8]).
This is relatively straight-forward. We know the type of our "seed" for the fold, it must be a pair of lists. We alternate which list of the two lists we're appending to by simply swapping the two lists, and we append to list on the left (which will change between each iteration).
foldr (\x (ys,zs) -> (x:zs, ys)) ([],[]) [2,4,6,8,7] -- ([2,6,7],[4,8])
If we were to use foldl the lists would come out backwards, so foldr seems like the logical choice.
Given a predicate p :: a -> Bool you can split on that using foldr as follows:
split :: (a -> Bool) -> [a] -> ([a],[a])
split p = foldr (\x (as, bs) -> if p x then (x:as, bs) else (as, x:bs)) ([],[])
For example:
Prelude> split (\x -> x `mod` 4 /= 0) [2,4,6,8,7]
([2,6,7],[4,8])