Comparing dates in list in Haskell - list
So I created this function which takes 2 items and compares them and returns the largest date.
biggerDate :: (Ord a1,Ord a2,Ord a3) => (a3,a2,a1)->(a3,a2,a1)->(a3,a2,a1)
biggerDate (x, x1, x2) (y, y1, y2) =
if x2 > y2
then (x, x1, x2)
else if x1 > y1 then (x, x1, x2) else (y, y1, y2)
Now I am trying to have a list of dates and compare all of them to find the largest date.
All I have two far is
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
I am stuck with trying to take 2 elements out of the list and compare them.
Let's think functionally and let the types guide us through this.
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate xs = ???
We take a list and... do something. Well, the first question is: what do we want to happen if the list is empty? There are a couple of ways we could handle this, but for our purposes we'll just say that was a mistake and signal an error
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate [] = error "Empty list of dates!"
maxDate (x : xs) = ???
Okay, the next simplest case is a single-element list. In that case, the biggest date is obviously the only one. After all, we've only got one choice.
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate [] = error "Empty list of dates!"
maxDate [x] = x
maxDate (x : xs) = ???
Now we're left with the general case: there are several elements in our list. I've used pattern matching x : xs to extract the first one. What we want to do now is figure out which is bigger: the first element or the rest of the list. We can figure out what the biggest element in the rest of the list is with recursion: maxDate xs. Then we need to figure out whether that thing is bigger than or smaller than the first element x. You already wrote a function to do that, so let's use it.
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate [] = error "Empty list of dates!"
maxDate [x] = x
maxDate (x : xs) = biggerDate x (maxDate xs)
And now we have a working implementation. But let's not stop there. Let's make it better.
First off, notice that we could do this for any binary function on (a3, a2, a1), not just biggerDate. Let's abstract our function a bit and take an additional argument
foldDate :: (Ord a1, Ord a2, Ord a3) => ((a3, a2, a1) -> (a3, a2, a1) -> (a3, a2, a1)) -> [(a3, a2, a1)] -> (a3, a2, a1)
foldDate _ [] = error "Empty list!"
foldDate _ [x] = x
foldDate f (x : xs) = f x (foldDate f xs)
I've added an additional argument to make our function more useful in general. Now, maxDate is just a special case of foldDate.
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldDate biggerDate
But we can go further, as it turns out, foldDate doesn't really need its arguments to be dates at all. It can work on any types.
fold :: (a -> a -> a) -> [a] -> a
fold _ [] = error "Empty list!"
fold _ [x] = x
fold f (x : xs) = f x (fold f xs)
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = fold biggerDate
Now, there's a very useful tool in Haskell called Hoogle. You can plug a type signature into it, and it'll tell you if something matching that signature is built-in or in a well-known Haskell library. Let's plug in our abstracted fold function's type: (a -> a -> a) -> [a] -> a. One of the first results is a function called foldr1. While the source is a bit more complex than what we've written here, it turns out foldr1 is literally the exact function we want. We didn't even need to write a fold function ourselves; it's already built-in.
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldr1 biggerDate
Great! maxDate is just two words now. That's pretty snazzy. But we can work on biggerDate too. See, as it turns out, Ord has an instance for 3-tuples of things, which automatically sorts starting with the first element, then the second, then the third. So, if you're willing to orient your dates in YMD order (rather than DMY as it looks like you're doing now), your biggerDate can get simpler as well.
biggerDate :: (Ord a1,Ord a2,Ord a3) => (a3, a2, a1) -> (a3, a2, a1) -> (a3, a2, a1)
biggerDate x y = if x > y then x else y
If you still want the dates to print in DMY format, you can always define a custom datatype (data Date = Date Int Int Int) with its own Show instance, but for now we'll just use YMD since it makes some things simpler.
Okay, but again, let's abstract. That function didn't do anything with tuples, so it should work for any Ord things, right?
bigger :: Ord a => a -> a -> a
bigger x y = if x > y then x else y
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldr1 bigger
Okay, that type signature looks pretty abstract now. Let's hop over to Hoogle once again. Lo and behold, the bigger function is built-in as well: it's called max. So we didn't even need bigger.
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = foldr1 max
Let's abstract once again. This version of maxDate didn't really use tuples either, so its type signature could be as general as Ord a => [a] -> a. One more trip through Hoogle tells us that even that function is available in Haskell. So our final definition is
maxDate :: (Ord a1, Ord a2, Ord a3) => [(a3, a2, a1)] -> (a3, a2, a1)
maxDate = maximum
The function maxDate is literally built-in to Haskell, if you know how to use the abstraction techniques at your disposal.
The reason I go through all of this in such detail is exactly that. It's valuable, especially when starting out, to be prepared to write these recursive definitions yourself, and I recommend you do so. In fact, just going through the standard library (Data.List in particular is a goldmine) and implementing the functions you see there by hand is a wonderful exercise when learning Haskell.
But it's also important to note that a lot of common design patterns are captured well by the standard library. Your pattern of "I have a binary function and I want to collapse a list" was captured by foldr1 (and its family of fold functions), and even more generally, your pattern of "I want the biggest thing in this list, for some definition of 'biggest'" was captured by the maximum function. This is why people use Haskell; it does a whole lot with its polymorphism capabilities and provides a relatively small standard library (compared to, say, Java) that turns out to be far more useful than it appears at first glance, based on its size, and captures a lot of higher-order programming patterns very elegantly.
Related
How to filter my list of tuples of two input lists?
I am trying to generate all possibles combinations from two lists and then only return those that match the lambda function. So I currently have the following code: func :: [a] -> [b] -> ((a, b) -> Bool) -> [(a, b)] func xs ys f = filter f (tup) where tup = concat(map (\x -> map (\y -> (x,y))ys) xs) Currently I am able to generate all the possible combinations, but the filtering won't work. Error for the input : func [1,2,3] [4,5] (\ a b -> a+b > 6) • Couldn't match expected type ‘Bool’ with actual type ‘(a, b) -> Bool’ • The lambda expression ‘\ a b -> a + b > 7’ has two value arguments, but its type ‘(a, b) -> Bool’ has only one How can I solve this? I tried to use map instead of filter, but that did not work as well.
Making a function with two arguments and making a function with a single 2-tuple argument use slightly different syntax: \a b -> a+b > 6 -- two arguments \(a, b) -> a+b > 6 -- one tuple argument
haskell: calling a function with different types of lists
I have a function: sum f l1 l2 = (f l1) + (f l2) How to correct this function to be working when called with different types of lists? eg: sum length [1,2] ['a','b']
May as well flesh out my comment in an answer. The usual signature one may be tempted to give is sum :: Num b => ([a] -> b) -> [a] -> [a] -> b sum f l1 l2 = f l1 + f l2 The problem here is that the two lists must have the same type, which must be the input type of the function. The solution is to tell GHC that the function actually has the more general type forall a. [a] -> b, which means that we can pick multiple possibly different a instantiations and they all produce the same b. {-# LANGUAGE RankNTypes #-} sum' :: Num b => (forall a. [a] -> b) -> [c] -> [d] -> b sum' f l1 l2 = f l1 + f l2 main = print $ sum' length [1,2] ['a','b']
There's no general way to do this at the moment unfortunately. You could try like this previous answer suggested as follows: sum' :: Num b => (forall a. [a] -> b) -> [c] -> [d] -> b sum' f l1 l2 = f l1 + f l2 And whilst this works with length, it doesn't really work with much else. The issue is that the type signature in this answer Num b => forall a. [a] -> b. That means your function must work for all types of lists, and the only sensible function from Num b => forall a. [a] -> b is length. If you think there's another feel free to give me an example, but I suspect all the other examples are either variations of length or silly ones that return a constant. And if length is the only sensible argument for sum', then it's silly to define sum', you might as well define sumLength like follows sumLength :: Num b => [c] -> [d] -> b sumLength l1 l2 = genericLength l1 + genericLength l2 Indeed, lets define the following: g :: Enum a => [a] -> Int g = (foldl' 0 (+)) . (map fromEnum) This is a weird probably useless function, but it does something non-trivial. It converts all the values to their Enum int representation and sums them and spits out an Integer. So sum' g l1 l2 should work, but it doesn't. To get this to work, you'd have to define a new function: sum'' :: Enum c, Enum d => (Enum a => forall a. [a]) -> [c] -> [d] -> Int sum'' f l1 l2 = f l1 + f l2 And indeed, too use any function with different constraints, you'll have to define a new version of sum. So really, no, there's no way to answer your question similarly. I recognised this problem and created the package polydata, which you can check out on hackage (needs some clearer documentation I admit). It does allow you to make functions which accept polymorphic functions that you can apply to different types, like so: g :: (c (a -> a'), c (b -> b')) => Poly c -> (a, b) -> (a' -> b') g f (x,y) = (getPoly f x, getPoly f y) Which is very similar to your example. c in the above is a constraint, and looking at the type of g should help you understand what's happening. Unfortunately, you can't just pass an ordinary function to g, you have to pass one wrapped in a Poly, which is non trivial as you don't get type inference for the Poly constraint (any ideas on how to make this nicer appreciated). But if you've just got one or a few functions that need this polymorphic behaviour, I wouldn't bother with Poly. But for example, you're finding this issue coming up a lot (I found it came up a lot in unit testing, which is what inspired the creation of my package), then you might find polydata useful. There's also heterolist, which I created as an extension to polydata allows you to create lists of mixed types and say, map over them in a type safe way. You might find that useful.
Modeling recursive fmap (sort of) over a list
I was wondering what the best way is to implement the following problem in a functional programming language (in this example Haskell): You have a function (or a 'way') that turns 2 inputs, with the type a and b, in 2 ouputs of the same type (ex: Half adder). Lets call it f in Haskell it would have this sort of type signature a -> b -> (a, b) And you have a list with elements of type a. (or another type of data structure). Now if supplied with an initial b I want the following thing to happen (concept explained with recursive implementation): Execute f with the initial b and the first element, modify the b and the element with the output of the function and repeat for the next element. In Haskell: exec _ [] _ = [] exec f (x:xs) b = let (x',b') = f x b in x':(exec f xs b') What would be the best/most efficient way to model this sort of behavior.
It's mapM for the State monad. OK, expanding a little. Let's first enter this into ghci and see the type of the exec function: Prelude> let {exec _ [] _ = []; exec f (x:xs) b = let (x',b') = f x b in x':(exec f xs b')} Prelude> :t exec exec :: (t2 -> t1 -> (t, t1)) -> [t2] -> t1 -> [t] It's almost as you described, except that t and t2 don't have to be of the same type. That's good. Now, another observation: we actually lose information, when we do what you describe. Specifically, we throw away the last value of b (or t, as ghci calls it). Let us preserve it for a moment; we can always throw it away later: exec' _ [] b = ([], b) exec' f (x:xs) b = let (x',b') = f x b (xs', b'') = exec' f xs b' in (x':xs', b'') And ghci says Prelude> :t exec' exec' :: (t2 -> t1 -> (t, t1)) -> [t2] -> t1 -> ([t], t1) Than we can define exec f xs b = fst $ exec' f xs b But now the type of exec' contains a clear pattern. We can make it more explicit: type S b c = b -> (c, b) exec' :: (a -> S b c) -> [a] -> S b [c] And now it's clear that S is almost exactly the State monad (well, it's actual definition in a modern setting is a bit more complicated, but not much: https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-State-Lazy.html#t:StateT); really, it's just a newtype: newtype State b c = State {runState :: b -> (c, b)} And if we generalize the type of exec' to use an arbitrary monad instead of State, we get Monad m => (a -> m c) -> [a] -> m [c] Of course, we can't know for sure that such a thing actually exists, since we only have an implementation for the State monad, but... it does. It's called mapM (again, it's actual definition in the modern setting is more complicated: https://hackage.haskell.org/package/base-4.9.1.0/docs/Prelude.html#v:mapM) — which makes sense, since without a monad it would be just (a -> c) -> [a] -> [c] and that's exactly the type of map. Of course, you can't be sure that exec' IS mapM without examining the latter's implementation. But in Haskell it just often happens that things that have the same type, if it's reasonably generic, are one and the same. It also makes sense that State monad would be involved somehow — after all, you DO use b as a state, changing it as you go through the list. So, if exec' is mapM, how do we get back to exec? Well, we need to go from the monadic value State b [c] to just [c], feeding it some b. We can — again — generalize; let's say, we go from State b d to d, without mentioning the list. And again — there is a function like that, it's called evalState: https://hackage.haskell.org/package/mtl-2.2.1/docs/Control-Monad-State-Lazy.html#v:evalState. So, finally, we are able to produce the final result: eval f xs b = evalState (mapM (\x -> state (\b -> f x b)) xs) b which we can shorten to eval f xs b = evalState (mapM (\x -> state (f x)) xs) b or just eval f xs = evalState (mapM (state . f) xs) or even eval f = evalState . mapM (state . f) We can make it completely point-free, but that would be pointless (and contain too many points): eval = (evalState .) . mapM . (state .)
Access elements of tuple in list in Haskell
I have a list of tuples, for example: [(1,2), (3,4), (5,6)] Now I have to write function which sum up the first an second element of each tuple and create a list of these values. For the example above it should be: [3, 7, 11] This should be done with use of list comprehension. It's not allowed to use functions like map, filter and contact. Any ideas how I could access the elements of the tuple in the list?
Try this: [ x + y | (x,y) <- yourlist] The trick is representing the two elements in a tuple from your input list as x and y and then dealing with them as needed.
Let's do it without list comprehensions, using functions from the Prelude: map (uncurry (+)) [(1,2), (3,4), (5,6)] -- Result: [3, 7, 11] How does this work? Let's consider the types: (+) :: Num a => a -> a -> a uncurry :: (a -> b -> c) -> (a, b) -> c map :: (a -> b) -> [a] -> [b] As you may already know, in Haskell, the normal way of doing multi-argument functions is by **currying* them. The type of (+) reflects this: conceptually it takes one argument and produces a function that then takes the "second" argument to produce the final result. uncurry takes such a curried two-argument function and adapts it to work on a pair. It's trivial to implement: uncurry :: (a -> b -> c) -> (a, b) -> c uncurry f (a, b) = f a b Funnily enough, the uncurry function is curried, so its partial application uncurry (+) has type Num a => (a, a) -> a. This would then be a function that takes a pair of numbers and adds them. And map simply applies a function to every element of a list, collecting the individual results into a list. Plug them all together and that's a solution.
Writing a function List to a tuple
how to write a function from list to a tuple i have taken the string to a tuple. but i need to send it to a tuple. can someone help me
You can't convert an arbitrarily long list to a tuple because tuples of different lengths are considered as distinct types. But you can have: listToTuple2 :: [a] -> (a, a) listToTuple3 :: [a] -> (a, a, a) listToTuple4 :: [a] -> (a, a, a, a) listToTuple5 :: [a] -> (a, a, a, a, a) etc. See also http://www.haskell.org/haskellwiki/Template_Haskell#Convert_the_first_n_elements_of_a_list_to_a_tuple.