So I have a list of tuples:
[(1,2),(2,3),(3,4)]
for example. And I perform a calculation on its elements. The result of this should be joined to this tuple, but I don't know how.
[(1,2,103),(2,3,809),(3,4,2034)]
is the format I'm thinking of.
Assuming you have a calculation function like:
calculate :: Int -> Int -> Int
you can do
calculateAll :: [(Int, Int)] -> [(Int, Int, Int)]
calculateAll = map (\(x, y) -> (x, y, calculate x y))
or more generally:
calculateAllWith :: (a -> b -> c) -> [(a, b)] -> [(a, b, c)]
calculateAllWith f = map (\(x, y) -> (x, y, f x y))
A quite straightforward solution:
import Control.Applicative ((<*>))
mapResultOn3rd :: (a -> b -> c) -> [(a,b)] -> [(a,b,c)]
mapResultOn3rd f = map (uncurry (,,) <*> uncurry f)
For example, in ghci:
>>> mapResultOn3rd (:) [(1,[2]), (3,[4,5])]
[(1,[2],[1,2]),(3,[4,5],[3,4,5])]
Use the map function:
calc :: (Int, Int) -> (Int, Int, Int)
calc = error "Implement me"
calcList :: [(Int, Int)] -> [(Int, Int, Int)]
calcList = map calc
You could also use a list comprehension in GHCi:
Prelude> let list = [(1,2),(2,3),(3,4)]
Prelude> [(x,y,x*y) | (x,y) <- list]
[(1,2,2),(2,3,6),(3,4,12)]
http://www.haskell.org/haskellwiki/List_comprehension
Or use the list as a monad:
Prelude> do (x,y) <- list; return (x,y,x*y)
[(1,2,2),(2,3,6),(3,4,12)]
But I prefer the list comprehension :-)
Related
I am new to haskell and am trying to make a function which will shuffle a list of objects. However, I keep getting ambiguous type errors, I also got one from the 'cmp' function as well.
cmp :: Ord b => (a, b) -> (a, b) -> Ordering
cmp (x1,y1) (x2,y2) = compare y1 y2
--shuffleStack is giving me ambiguous type errors when running, one for randoms and one for cmp
shuffleStack :: StdGen -> [a] -> [a]
shuffleStack g domSet = [x | (x,y) <- sortBy cmp (zip domSet (randoms g))]
--This function nearly does the same thing but doesn't give any errors
test g domSet = sortBy cmp (zip domSet (randoms g))
Does anybody know what I am doing wrong? Thanks!
The problem is that because you later remove the second element of the 2-tuples, this thus means that the type of the random elements b, is not in the signature anymore, and thus can be anything.
You should give it a hint what type to use, for example an Int:
shuffleStack :: StdGen -> [a] -> [a]
shuffleStack g domSet = [x | (x,y) <- sortBy cmp (zip domSet (randoms g :: [Int]))]
Note that you can make use of sortOn :: Ord b => (a -> b) -> [a] -> [a]:
import Data.List(sortOn)
shuffleStack :: StdGen -> [a] -> [a]
shuffleStack g domSet = [x | (x,y) <- sortOn snd (zip domSet (randoms g :: [Int]))]
You can also perform a mapping to get rid of the second item of the 2-tuples. We can also swap the order of the items of the 2-tuple to eliminate the explicit domSet parameter:
import Data.List(sortOn)
shuffleStack :: StdGen -> [a] -> [a]
shuffleStack g = map snd . sortOn fst . zip (randoms g :: [Int])
For example we can shuffle a list of Ints with a seeded pseudo-random generator:
Prelude System.Random Data.List> shuffleStack (mkStdGen 0) [1,4,2,5]
[4,5,2,1]
I'm writing a function that compares two vectors in haskell using comprehension lists. The thing is that I want to add booleans to my final list, but Haskell interprets this code as if x == y, add the element to the list (that's how comprehensive lists works I know). What I want is a list with booleans if the coordinates I'm comparing are true or false.
Is it possible to do this with comprehension lists?
igualdad :: Vector -> Vector -> [Bool]
igualdad v1 v2 = [ x == y | x <- xs, y <- ys]
where xs = vectorToFloatList v1
ys = vectorToFloatList v2
PD: I'm going to use foldr (&&) True with the list that returns igualdad, in order to get the final result that I want.
Thanks.
What I want is a list with booleans if the coordinates I'm comparing are True or False. Is it possible to do this with comprehension lists?
You get such a list. For two Vectors v and w with lengths m and n respectively, you will get a list with m×n elements, such that the item vi and wj will be compared in the result list in the element with index i×m + j.
If you hwever want a list of length min(m, n), such that the item at index i checks if vi and wi are the same, then we can make use of zip :: [a] -> [b] -> [(a, b)]:
igualdad :: Vector -> Vector -> [Bool]
igualdad v1 v2 = [ x == y | (x, y) <- zip (vectorToFloatList xs) (vectorToFloatList ys)]
or with zipWith :: (a -> b -> c) -> [a] -> [b] -> [c] and on :: (b -> b -> c) -> (a -> b) -> a -> a -> c:
import Data.Function(on)
igualdad :: Vector -> Vector -> [Bool]
igualdad = on (zipWith (==)) vectorToFloatList
or we can make use of the ParallelListComp extension [ghc-doc] and run this with:
{-# LANGUAGE ParallelListComp #-}
igualdad :: Vector -> Vector -> [Bool]
igualdad v1 v2 = [ x == y | x <- vectorToFloatList xs | y <- vectorToFloatList ys]
PD: I'm going to use foldr (&&) True with the list that returns igualdad.
There exists a function for that already: that is and :: Foldable f => f Bool -> Bool. If you however want to check if all the items are the same, you can just use all :: Foldable f => (a -> Bool) -> f a -> Bool here:
import Data.Function(on)
sameVec :: Vector -> Vector -> Bool
sameVec = on (all (uncurry (==) .) . zip) vectorToFloatList
I have a function like this:
[(String, [Int], Int)]
I desire a function that just returns a list of [Int].
Input example:
[("R1",[6,10,14],6),("R2",[8,10,14],8),("R3",[11,15,24],11)]
Output example (the behavior that I want of the output):
[6,8,10,11,14,15,24]
I've been thinking to create a function of input, like this:
function :: [(String, [Int], Int)]
function = [("R1",[6,10,14],6),("R2",[8,10,14],8),("R3",[11,15,24],11)]
And another to convert to what I desire, like this :
convert :: [(String, [Int], Int)] -> [Int]
convert [] = []
...
How can I develop the function convert?
First thing I like to do is lay out all the type signatures I think I'll need:
-- Something to use with fmap to get rid of the Strings
f :: (String, [Int], Int) -> ([Int], Int)
-- Something to cons the list with the Int
g :: ([Int], Int) -> [Int]
-- Our final goal:
convert :: [(String, [Int], Int)] -> [Int]
Now I like to think about how I can compose these together to get my final result:
fmap g . fmap f :: [(String, [Int], Int)] -> [[Int]]
And thanks to the functor laws you can actually rewrite that as:
fmap (g . f) :: [(String, [Int], Int)] -> [[Int]]
Thats pretty close, but we have two nested lists instead of one. Luckily list is a monoid which means that we can use mconcat :: [a] -> a to fold it. Thats a little confusing because mconcat operates on a list of monoidal a values. The more concrete signature for mconcat in our case would be:
mconcat :: [[Int]] -> [Int]
Where the monoid we are mappending is the inner list.
Regardless, what that allows us to do is write this:
mconcat . fmap (g . f) :: [(String, [Int], Int)] -> [Int]
Which is exactly the function we are trying to implement:
convert :: [(String, [Int], Int)] -> [Int]
convert = mconcat . fmap g . fmap f
where f = undefined
g = undefined
Now we just need to implement f and g:
f :: (String, [Int], Int) -> ([Int], Int)
f (_, xs, x) = (xs, x)
g :: ([Int], Int) -> [Int]
g (xs, x) = x:xs
g' :: ([Int], Int) -> [Int]
g' (xs, x) = xs ++ [x]
Depending what position you want x to go in you can use g or g'.
Then your final implementation would be something like (sort added to the composition to match your example result):
convert :: [(String, [Int], Int)] -> [Int]
convert = sort . mconcat . fmap g . fmap f
where f (_, xs, x) = (xs, x)
g (xs, x) = x:xs
Looking back at your question, it looks like the 3rd element of the triple is always a member of the second element? If thats the case, this function becomes even simpler:
convert :: [(String, [Int], Int)] -> [Int]
convert = sort . mconcat . fmap f
where f (_, xs, ) = xs
If you are worried about performance due to the final sort step, you could combine it with the concatenation by using foldr to rather then mconcat and do the sorting in the a -> b -> b.
I have a list of constants and degrees of a polynomial equation and want to return a list of this composition for a value be applied and then summed. But this list comes as Int and my function expects a list of double.
poly :: [Double] -> [Double] -> [Double -> Double]
poly a b =
let f x y = (*x) . (**y)
in uncurry f <$> zip a b
-- does not work
poly ([1,2,3]:: [Double]) ([1,2,3]:: [Double])
How to cast a list of int to list of double?
You can use fromIntegral, which will convert from any Integral type into any Numeric type (Int, Integer, Rational, and Double).
More here: https://wiki.haskell.org/Converting_numbers
With #4castle and Victoria Ruiz I came up with the following:
poly :: [Int] -> [Int] -> [Double -> Double]
poly = zipWith $ \x y -> (* (fromIntegral x)) . (** (fromIntegral y))
apply :: Double -> [Double -> Double] -> Double
apply x b = sum $ ($x) <$> b
-- l=left limiting, r=right limiting, a=coeficients, b=degrees
solve :: Int -> Int -> [Int] -> [Int] -> [Double]
solve l r a b =
let h = 0.001
linspace = [fromIntegral l,fromIntegral l+h..fromIntegral r]
p = poly a b
area = sum $ map ((*h) . (`apply` p)) linspace
volume = h * (sum $ map ((*pi) . (**2) .(`apply` p)) linspace)
in [area,volume]
I think Haskell compiler with his strong type inference has some peculiarities that can't be directly solved by type cast.
I have to write a Haskell program that does the following:
Main> dotProduct [(1,3),(2,5),(3,3)] 2
[(2,3),(4,5),(6,3)]
I have to do it both with and without map function.
I already did it without map, but I have no clue to do it with map.
My dotProduct without map function:
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct [] _ = []
dotProduct [(x,y)] z = [(x*z,y)]
dotProduct ((x,y):xys) z = (x*z,y):dotProduct (xys) z
So I really need help with the map version.
Rather than starting by trying to fit map in somehow, consider how you might simplify and generalize your current function. Starting from this:
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct [] _ = []
dotProduct [(x,y)] z = [(x*z,y)]
dotProduct ((x,y):xys) z = (x*z,y):dotProduct (xys) z
First, we'll rewrite the second case using the (:) constructor:
dotProduct ((x,y):[]) z = (x*z,y):[]
Expanding the [] in the result using the first case:
dotProduct ((x,y):[]) z = (x*z,y):dotProduct [] z
Comparing this to the third case, we can see that they're identical except for this being specialized for when xys is []. So, we can simply eliminate the second case entirely:
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct [] _ = []
dotProduct ((x,y):xys) z = (x*z,y):dotProduct (xys) z
Next, generalizing the function. First, we rename it, and let dotProduct call it:
generalized :: [(Float, Integer)] -> Float -> [(Float, Integer)]
generalized [] _ = []
generalized ((x,y):xys) z = (x*z,y):generalized (xys) z
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized xs z
First, we parameterize it by the operation, specializing to multiplication for dotProduct:
generalized :: (Float -> Float -> Float) -> [(Float, Integer)] -> Float -> [(Float, Integer)]
generalized _ [] _ = []
generalized f ((x,y):xys) z = (f x z,y):generalized f (xys) z
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (*) xs z
Next, we can observe two things: generalized doesn't depend on arithmetic directly anymore, so it can work on any type; and the only time z is used is as the second argument to f, so we can combine them into a single function argument:
generalized :: (a -> b) -> [(a, c)] -> [(b, c)]
generalized _ [] = []
generalized f ((x,y):xys) = (f x, y):generalized f (xys)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (* z) xs
Now, we note that f is only used on the first element of a tuple. This sounds useful, so we'll extract that as a separate function:
generalized :: (a -> b) -> [(a, c)] -> [(b, c)]
generalized _ [] = []
generalized f (xy:xys) = onFirst f xy:generalized f (xys)
onFirst :: (a -> b) -> (a, c) -> (b, c)
onFirst f (x, y) = (f x, y)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (* z) xs
Now we again observe that, in generalized, f is only used with onFirst, so we again combine them into a single function argument:
generalized :: ((a, c) -> (b, c)) -> [(a, c)] -> [(b, c)]
generalized _ [] = []
generalized f (xy:xys) = f xy:generalized f (xys)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = generalized (onFirst (* z)) xs
And once again, we observe that generalized no longer depends on the list containing tuples, so we let it work on any type:
generalized :: (a -> b) -> [a] -> [b]
generalized _ [] = []
generalized f (x:xs) = f x : generalized f xs
Now, compare the code for generalized to this:
map :: (a -> b) -> [a] -> [b]
map _ [] = []
map f (x:xs) = f x : map f xs
It also turns out that a slightly more general version of onFirst also exists, so we'll replace both that and generalized with their standard library equivalents:
import Control.Arrow (first)
dotProduct :: [(Float, Integer)] -> Float -> [(Float, Integer)]
dotProduct xs z = map (first (* z)) xs
dotProduct xs z = map (\(x,y) -> (x*z,y)) xs
The (\(x,y) -> (x*z,y)) part is a function which takes a pair and returns a new pair that's like the old one, except its first component is multiplied by z. The map function takes a function and applies it to each element in a list. So if we pass the (\(x,y) -> (x*z,y)) function to map, it will apply that function to every element in xs.
Although are you sure your first one is correct? The dot product operation is usually defined so that it takes two vectors, multiplies corresponding component and then sums it all together. Like this:
dotProduct xs ys = sum $ zipWith (*) xs ys
EEVIAC already posted the answer, so I'll just explain how to come up with it yourself. As you probably know, map has the type signature (a -> b) -> [a] -> [b]. Now, dotProduct has the type [(Float, Integer)] -> Float -> [(Float, Integer)] and you'll call map somewhere in there, so it has to look something like this:
dotProduct theList z = map (??? z) theList
where ??? is a function of type Float -> (Float, Integer) -> (Float, Integer) - this follows immediately from the type signature of map and from the fact that we pass z to the function, which we have to do, simply because there's no other place to use it in.
The thing with map and higher order functions in general is that you have to keep in mind what the higher order function does and "simply" supply it with the correct function. As map applies a given function to all elements in the list, your function only needs to work with one element, and you can forget all about the list - map will take care of it.