Related
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.
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 .)
I have a question about head, tail, init and last.
The following works in GHCi:
Prelude Data.List Data.Char> let n = [1..10] in (head n : tail n)
[1,2,3,4,5,6,7,8,9,10]
As expected, I get the whole list. So this should work for init and last too,
right?
Prelude Data.List Data.Char> let n = [1..10] in (init n : last n)
<interactive>:39:1:
Non type-variable argument in the constraint: Enum [[a]]
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a. (Enum a, Enum [[a]], Num a, Num [[a]]) => [[a]]
If I look at the type signatures for the functions, then head and last
look the same -- they both return an element. Also init and tail look
the same, because they both return lists.
Prelude Data.List Data.Char> :info head
head :: [a] -> a -- Defined in ‘GHC.List’
Prelude Data.List Data.Char> :info tail
tail :: [a] -> [a] -- Defined in ‘GHC.List’
Prelude Data.List Data.Char> :info init
init :: [a] -> [a] -- Defined in ‘GHC.List’
Prelude Data.List Data.Char> :info last
last :: [a] -> a -- Defined in ‘GHC.List’
So what does Non type-variable argument in the constraint: Enum [[a]] mean?
If I do init n or last n without the construction of a new list, I get
[1..9] and 10.
Ahh snap, : takes an element and the rest like in x:xs, not a list and the last element, like in xs:x.
Prelude Data.List Data.Char> :info :
data [] a = ... | a : [a] >·-- Defined in ‘GHC.Types’
infixr 5 :
data [] a = ... | a : [a] >·-- Defined in ‘GHC.Types’
infixr 5 :
I still would like to know how you understand GHCi error messages and I have to wait 2 days to accept my own answer anyway.
Edit: I get that x and xs are only variable names chosen by convention, and (xs:_) would match the head but is unconventionally/confusingly named.
Edit 2: I upvoted and accepted Daniel Wagner's answer, because he explained the error message step by step. Really nice! Thank you!
It is true that head/last and tail/init have identical types. So if you had simply swapped out last for head and init for tail, you would have had no problem:
> let n = [1..10] in last n : init n
[10,1,2,3,4,5,6,7,8,9]
But you didn't. You did both that swap and another: you changed the order of arguments to :. It so happens that : doesn't take two arguments of the same type:
> :t (:)
(:) :: a -> [a] -> [a]
So this last swap is not okay! In fact, if you give n a slightly more specific type signature, ghci will give a better error:
> let n :: [Integer]; n = [1..10] in init n : last n
<interactive>:1:50:
Couldn't match type ‘Integer’ with ‘[[Integer]]’
Expected type: [[[Integer]]]
Actual type: [Integer]
In the first argument of ‘last’, namely ‘n’
In the second argument of ‘(:)’, namely ‘last n’
This error is still not 100% clear, but I think with a bit of puzzling you can see what it's complaining about: since init n :: [Integer], and (:) :: [Integer] -> [[Integer]] -> [[Integer]], it's expecting last n :: [[Integer]] and therefore n :: [[[Integer]]]. But you explicitly said n :: [Integer], a conflict.
Now, what about the error it actually gave you in your case? Well, the clue is in the type of [1..10]:
> :t [1..10]
[1..10] :: (Enum t, Num t) => [t]
Notice that [1..10] is polymorphic. Moreover, it is used twice in your expression, and so it can be given separate monomorphic types in the two uses. So [1..10] is instantiated with two different types in the sequel!
Now I think you can start to see where the error you got comes in. It's trying to find a type a for which:
Enum a -- this is needed to do the .. part of init [1..10]
Num a -- this is needed to do the 1 and 10 parts of init [1..10]
Enum [[a]] -- if init n :: a, then to have init n : last n be well-typed, we must have last n :: [a] and hence the second occurrence of n must have n :: [[a]]; then the Enum constraint is needed for the .. part of last [1..10]
Num [[a]] -- by similar reasoning, this is needed to do the 1 and 10 parts of last [1..10]
But these constraints together are hard to satisfy -- certainly there's no instance of Enum and Num for lists in scope in the Prelude or Data.List. So it complains.
In larger programs there is more type information (implicit and explicit) allowing the compiler to do a better job inferring types than in one-line snippets provided to GHCi. As a result, the errors you see in GHCi are not representative of what is typically observed when building a full program.
That said, it's no excuse for the awfulness that is the error you posted:
Prelude> let n = [1..10] in (init n : last n)
<interactive>:8:1:
Non type-variable argument in the constraint: Enum [[a]]
(Use FlexibleContexts to permit this)
When checking that ‘it’ has the inferred type
it :: forall a. (Enum a, Enum [[a]], Num a, Num [[a]]) => [[a]]
So there is a lot of polymorphism involved in your own line. You have lists of Num a (Num a => [a]) where the type variable a must itself be alist since you've used : last n where last n :: [_] ~ a. So this, combined with the fact that .. in list comprehension implies an enum, is how we got to the horrible message.
Let's look at the simpler case where we've told GHCi our list is of type [Int]:
Prelude> let n = [1..10] :: [Int] in (init n : last n)
<interactive>:7:44:
Couldn't match type ‘Int’ with ‘[[Int]]’
Expected type: [[[Int]]]
Actual type: [Int]
In the first argument of ‘last’, namely ‘n’
In the second argument of ‘(:)’, namely ‘last n’
Ahh, much better. Column 44 is the n in last n. It says that last n :: Int. So the type of init n : when init n :: [Int] means our cons function type is (:) :: [Int] -> [[Int]] -> [[Int]]. But wait! [[Int]] needed for the argument of init n : does not match Int provided by last n!
I have a custom list type:
data NNList a = Sing a | Append ( NNList a) ( NNList a) deriving (Eq)
data CList a = Nil | NotNil ( NNList a) deriving (Eq)
I'm trying to implement a function that returns the head and tail of a list:
cListGet :: CList a -> Maybe (a, CList a)
My attempt:
cListGet :: CList a -> Maybe (a, CList a)
cListGet Nil = Nothing
cListGet xs#(NotNil nxs) =
case nxs of
Sing x -> (x, Nil)
Append l r -> ((fst $ cListGet (NotNil l)), (Append (snd $ cListGet (NotNil l)), r))
Which to me means keep going leftwards until I get a single. Once I get the single element (head), return the element and a Nil list. This Nil list is then combined with the list before it's returned as the final result.
I'm not even sure if the logic is 100% correct.
Well, people would normally refer to the data structure you have as a kind of tree, not as a list. But anyway...
Problem #1: Haskell is indentation sensitive, and your case expression is not indented. This leads to a parse error.
Problem #2, and the bigger one: you haven't understood how the Maybe type works yet. I get the impression that you think it works like nulls in more common languages, and this is throwing you off.
In a language like, say, Java, null is a value that can occur where most any other value can. If we have a method with the following signature:
public Foo makeAFoo(Bar someBar)
...then it is legal to call it either of these ways:
// Way #1: pass in an actual value
Bar theBar = getMeABar();
Foo result = makeAFoo(theBar);
// Way #2: pass in a null
Foo result2 = makeAFoo(null)
theBar and null are "parallel" in a sense, or said more precisely, they have the same type—you can replace one with the other in a program and it will compile in both cases.
In Haskell, on the other hand, the string "hello" and Nothing do not have the same type, and you cannot use one where the other goes. Haskell distinguishes between these three things:
A string that's required to be there: "hello" :: String
The absence of an optional string: Nothing :: Maybe String
The presence of an optional string: Just "hello" :: Maybe String
The difference between #1 and #3 is what you're systematically missing in your function. With Maybe a, in the cases where you do have a value you must use Just, which acts like a wrapper to signify "this isn't just an a, it's a Maybe a."
First place you're missing Just is the right hand sides of the case expressions, which we can fix like this:
-- This still fails to compile!
cListGet :: CList a -> Maybe (a, CList a)
cListGet Nil = Nothing
cListGet xs#(NotNil nxs) =
case nxs of
-- I added 'Just' here and in the next line:
Sing x -> Just (x, Nil)
Append l r -> Just (fst $ cListGet (NotNil l), (Append (snd $ cListGet (NotNil l)), r))
But this isn't the end of it, because you're doing fst $ cListGet (NotNil l), which suffers from the converse problem: cListGet returns Maybe (a, CList a), but fst works on (a, b), not on Maybe (a, b). You need to pattern match on the result of cListGet to test whether it's Nothing or Just (x, l'). (This same problem occurs also in your snd $ cListGet (NotNil l).)
Third, you're using your Append constructor wrong. You have it in the form of (Append foo, bar), which should have no comma between foo and bar. In Haskell this sort of thing will give you more confusing error messages than most other languages, because when Haskell sees this, it doesn't tell you "you made a syntax error"; Haskell is rather more literal than most languages, so it figures you're trying to make a pair with Append foo as the first element, and bar as the second one, so it concludes that (Append foo, bar) must have type (NNList a -> NNList a, NNList a).
The fourth and final problem: the problem you've set yourself is not clearly stated, and thus has no good answer. You say you want to find the "head" and "tail" of a CList a. What does that mean? In the case of the Haskell [a] type, with constructors [] and :, this is clear: the head is the x in x:xs, and the tail is the xs.
As I understand you, what you mean by "head" seems to be the leftmost element of the recursive structure. We could get that this way:
cListHead :: CList a -> Maybe a
cListHead Nil = Nothing
-- No need to cram everything together into one definition; deal with
-- the NNList case in an auxiliary function, it's easier...
cListGet (NotNil nxs) = Just (nnListHead nxs)
-- Note how much easier this function is to write, because since 'NNList'
-- doesn't have a 'Nil' case, there's no need to mess around with 'Maybe'
-- here. Basically, by splitting the problem into two functions, only
-- 'cListHead' needs to care about 'Maybe' and 'Just'.
nnListHead :: NNList a -> a
nnListHead (Sing a) = a
nnListHead (Append l _) = nnListHead l
So you might think that "the tail" is everything else. Well, the problem is that "everything else" is not a subpart of your CList or NNList. Take this example:
example :: CList Int
example = NotNil (Append (Append (Sing 1) (Sing 2)) (Sing 3))
The "head" is 1. But there is no subpart of the structure defined in example that contains 2 and 3 without containing 1 as well. You'd have to construct a new CList with a different shape than the original to get that. That's possible to do, but I don't see the value of it as a beginner's exercise, frankly.
In case it's not clear what I mean by a "subpart," think of the example as a tree:
NotNil
|
v
Append
/ \
v v
Sing Append
| / \
v v v
1 Sing Sing
| |
v v
2 3
Subpart = subtree.
Hint: try to rewrite this using only pattern matching and not equality-checking (==).
Edit:
First off, it's crucial that you understand what pattern matching is and how it works. I'd recommend going here and reading up; there are also plenty of other resources about this on the web (Google is your friend).
Once you've done that, here's another hint: First write a function nnListGet :: NNList a -> (a, CList a), then use it to implement cListGet.
Just to add to the other (very thorough) answers: It's good to realize that your custom list is a foldable structure. This means, it represents a sequence of values that can be combined together. Such datatypes can implement Foldable type class. In your case, it would be:
import Prelude hiding (foldr)
import Data.Foldable
data NNList a = Sing a | Append (NNList a) (NNList a) deriving (Eq)
data CList a = Nil | NotNil (NNList a) deriving (Eq)
instance Foldable NNList where
foldr f z (Sing x) = f x z
foldr f z (Append xs ys) = foldr f (foldr f z ys) xs
instance Foldable CList where
foldr _ z Nil = z
foldr f z (NotNil xs) = foldr f z xs
From that you'll get all functions defined in Data.Foldable for free, such as maximum/minimum, searching for an element etc.
For any Foldable, you can implement headMaybe that returns its first element by using First monoid. It's a very simple monoid that returns the left-most non-empty element. So if you fold all elements of a Foldable using this monoid, you'll get its first one:
import Data.Monoid
headMaybe :: (Foldable f) => f a -> Maybe a
headMaybe = getFirst . foldMap (First . Just)
(Alternatively, you can use foldr directly, using Maybe's instance of Alternative, which again returns the left-most non-empty element:
import Control.Applicative
headMaybe = foldr (\x y -> pure x <|> y) Nothing
.)
However, this doesn't solve the second part of your question - computing tailMaybe. This can't be defined in a generic way like headMaybe, and you'll need your custom function for that, as you did.
See also:
Fold on Wikipedia.
Foldable and Traversable on Haskell wiki.
Fold on Haskell wiki.
List processing on Haskell wikibook.
Why did you declare that in terms of two types? Here's a seemingly more appropriate type declaration with a correct function:
data CList a
= Nil
| Sing a
| Append (CList a) (CList a)
deriving (Eq)
headAndTail :: CList a -> Maybe (a, CList a)
headAndTail Nil = Nothing
headAndTail (Sing a) = Just (a, Nil)
headAndTail (Append a b) =
case headAndTail a of
Nothing -> headAndTail b
Just (head, tail) -> Just (head, Append tail b)
For instance, i have a list like ['a','b','c','d','e'].
I want to do something like this:
First do something with the first two elements, f 'a' 'b'
Then do the same thing with the return value of f and next element in the list, result = f 'a' 'b', lets say like f result 'c'. Then f resultof(result 'c') 'd' and so on.
How can i do something like this?
First let's consider that function f that you have. It takes some sort of accumulated value, a plain value, and combines them into a result. So, in the type signature, we'll say a for the type of the accumulated value, v for the type of the value, and r for the type of the result.
f :: a -> v -> r
Now we want to create a folding function that uses f and a list of values.
someFold :: (a -> v -> r) -> [v] -> ?
What should it return? It should yield something of the resultant type r, right? Notice now that a and r should actually be the same type, since we keep feeding the result of f into it's first argument again.
someFold :: (a -> v -> a) -> [v] -> a
Now one thing's missing. How do you get the very first a? There are two ways to look at that. Either you just pick the first value, in which case a is the same type as v, or you specify a base value, so a could actually be different than v. Let's go with the latter, since that's more interesting. Let's also decide to move left to right in this list. (That's what you need, right?)
someFold :: (a -> v -> a) -> a -> [v] -> a
So...how do we implement it? It'll be recursive, so let's start with the base cases.
someFold f acc [] = acc
If we hit the end of the list, then we've accumulated enough, right? That was easy. So how about the recursive case? From what you said, at each step we should apply f to the "accumulated value so far" as the first argument, and the "first value of the list" as the second. f acc x. Then we keep folding, using that as our new "accumulated" value.
someFold f acc (x:xs) = someFold f (f acc x) xs
Easy, right? But...what if we want to do like you said and start the function by taking the first two values of the list? Also easy. Just take the first element, and call it the original "base" accumulator!
someFold1 :: (v -> v -> v) -> [v] -> v
someFold1 f (x:xs) = someFold f x xs
Notice that since a is the same type as v for this special case, the function someFold1 has a very amusing type signature. If you understood this explanation, then congrats. We've just implemented foldl and foldl1.
Prelude> foldl1 min "abcde" -- "abcde" is sugar for ['a','b','c','d','e']
'a'
In real code, you should actually use foldl' and friends.
Sounds like homework. Take a look at folds.
In this case, the problem with a fold is, that it usually processes on element at a time. You could try to manually roll a fold.
Assume, you have your function f, that gets two elements at a time and the accumulator (the result of the last iteration) fed. Then you function looks like this:
fold2 :: (a -> a -> b -> b) -> [a] -> b -> b
fold2 f accum (x:y:zs) = fold2 f (f x y) zs
fold2 _ accum [] = accum
fold2 _ _ _ = error "odd number of elements"
Try to understand this. fold2 shaves the top two elements of the list of and feeds it into f. The result this is then passed as the new accumulator to the recursive call. This is done until the list is empty.