I have a project where we are improving the speed of concatenating a list in Haskell.
I'm new to Haskell and confused about AList ([a] -> [a]) Specifically how to convert my AppendedList to a regular List. Any help would be appreciated.
newtype AppendedList a = AList ([a] -> [a])
-- List[5] is represented as AList (\x -> 5:x)
-- This function takes an argument and returns the AppendedList for that
single :: a -> AppendedList a
single m = AList (\x -> m : x)
-- converts AppendedList to regular List
toList :: AppendedList a -> [a]
toList = ???
The toughest part is to not give you the answer directly :)
If you remember how lists are constructed in Haskell: [1, 2, 3] = 1 : 2 : 3 : [], with [] being the empty list.
Now let's "follow the types" (we also call this thought process TDD for Type Driven Development) and see what you have at hand:
toList :: AppendedList a -> [a]
toList (AList listFunction) = ???
and listFunction has the type [a] -> [a]. So you need to provide it a polymorphic list (i.e. a list of any type) so that it gives you back a list.
What is the only list of any type you know of? Pass this list to listFunction and everything will compile, which is a good indicator that it's probably right :D
I hope that helps without providing the plain answer (the goal is for you to learn!).
AppendedList a is a type.
AList f is a datum of that type, with some function f :: [a] -> [a] "inside it".
f is a function from lists to lists with the same type of elements.
We can call it with some_list :: [a] to get resulting_list :: [a]:
f :: [a] -> [a]
some_list :: [a]
-------------------------
f some_list :: [a]
resulting_list :: [a]
resulting_list = f some_list
We can use resulting_list as some_list, too, i.e..
resulting_list = f resulting_list
because it has the same type, that fits f's expectations (and because of Haskell's laziness). Thus
toList (...) = let { ... = ... }
in ...
is one possible definition. With it,
take 2 (toList (single 5))
would return [5,5].
edit: Certainly [5,5] is not the list containing a single 5. Moreover, take 4 ... would return [5,5,5,5], so our representation contains any amount of fives, not just one of them. But, it contains only one distinct number, 5.
This is reminiscent of two Applicative Functor instances for lists, the [] and the ZipList. pure 5 :: [] Int indeed contains just one five, but pure 5 :: ZipList Int contains any amount of fives, but only fives. Of course it's hard to append infinite lists, so it's mainly just a curiosity here. A food for thought.
In any case it shows that there's more than just one way to write a code that typechecks here. There's more than just one list at our disposal here. The simplest one is indeed [], but the other one is .... our list itself!
Related
I'm trying to do a function in haskell. The purpose of the function is to add a list to an existing list of list.
[Int] -> [[Int]] -> [[Int]]
I wish it would work like :
[1] -> [[2],[3]] -> [[2],[3],[1]]
I would like to know how I can proceed to do that. There is an existing included function to do that?
You can wrap the element [1] in a singleton list, and then append the two lists with (++) :: [a] -> [a] -> [a]. So you can implement such function with:
addlast :: a -> [a] -> [a]
addlast x ys = ys ++ [x]
The (++) function however will usually take linear time in the number of elements of the left operand (so ys), which makes it computationally expensive. Therefore it is usually better if order does not matter to prepend to a list.
In the extra package [Hackage], you can make use of snoc :: [a] -> a -> [a]. In that case, this is thus a "flipped" version of snoc:
import Data.List.Extra(snoc)
addlast :: a -> [a] -> [a]
addlast = flip snoc
I am trying to create a function which adds a 1 before each of the entries in a given list. I haven't quite grasped the syntax for Haskell and am wondering what is wrong with this code. For example, I would like this to return the list [1,1,1,2,1,3]
ins1 :: [a] -> [a]
ins1 [x] = [x]
ins1 (x:xs) = [1] ++ [x] ++ ins1(xs)
main = print(ins1 [1,2,3])
I get the error:
• No instance for (Num a) arising from the literal ‘1’
Possible fix:
add (Num a) to the context of
the type signature for:
ins1 :: [a] -> [a]
• In the expression: 1
In the first argument of ‘(++)’, namely ‘[1]’
In the expression: [1] ++ [x] ++ ins1 (xs)
<interactive>:3:1: error:
• Variable not in scope: main
• Perhaps you meant ‘min’ (imported from Prelude)
Well like the error says, you use ins1, and you write [1] ++ [x] ++ ....
Now 1 is a numerical literal, so it can take all numerical types. Hence 1 has type Num b => b, as a result [1] has type Num b => [b].
Later you append the list with x and recursion, hence we now know that a ~ b (a and b are the same type). So we have to add a type constraint to the signature for a:
ins1 :: Num a => [a] -> [a]
ins1 [x] = [x]
ins1 (x:xs) = [1] ++ [x] ++ ins1(xs)
This solves the compile error, but probably will not generate what you want. Since now there is no case for the empty list. Indeed, both the [x] pattern and the (x:xs) pattern work with lists that respectively match with lists with exactly one element, and at least one element.
Therefore I think that your first clause should actually match the empty list:
ins1 :: Num a => [a] -> [a]
ins1 [] = []
ins1 (x:xs) = [1] ++ [x] ++ ins1(xs)
There is also an inefficiency in the second clause: you append to a list of one element, so we can use the "cons" data cosntructor (:) here:
ins1 :: Num a => [a] -> [a]
ins1 [] = []
ins1 (x:xs) = 1 : x : ins1 xs
This will insert a 1 for every element in the original list, so:
Prelude> ins1 [1, 4, 2, 5]
[1,1,1,4,1,2,1,5]
If you give me a function of type [a] -> [a], you’re saying that, for all types a that I choose, if I give you a list of values of type a, then you can give me back a list of elements of that type.
So if I choose a to be Int by giving you [2, 3, 4] :: [Int], then all is well: the literal 1 in the implementation of ins1 is constrained from Num t => t by t = Int to Num Int => Int. That works because there is an instance Num Int.
However, if I choose a to be Char, by giving you ['a', 'b', 'c'] (= "abc"), then t = Char, giving Num Char => Char, which is an error because there’s no instance Num Char. Therefore, this is a counterexample for the type: your function doesn’t work for all a, only those a that have an instance of Num. So you need to express this constraint in the type signature:
ins1 :: (Num a) => [a] -> [a]
The compiler can infer this for you, and will display a warning about a missing type signature if -Wall is enabled (or -Wmissing-signatures specifically). This will also warn about the fact that ins1 is non-exhaustive: you don’t handle the case of an empty input list. Alternatively, you can enter the definition into GHCi and ask for its type with :type ins1 or :t ins1.
Generic functions in Haskell are parametrically polymorphic, which means that if you have an unconstrained type variable like a, you know nothing about it, not even that it can be constructed from a number literal. So the only things a function of type [a] -> [a] can do are copy, rearrange, or drop elements from the input, or fail to terminate (loop infinitely or raise an error)—it can’t construct new elements or perform any class-specific operations on those elements, such as + from Num or < from Ord.
This may sound limiting, but in fact it’s incredibly useful: the less you know about a type, the fewer options you have for misusing it. And by a neat trick called the Curry–Howard correspondence, you can examine a polymorphic function type like head :: [a] -> a and think of it as a logical formula: does having a list of a imply you can get an a? No, because the list may be empty. So you know that a head function with this type must raise an error if the input is empty, because it has no generic way to construct an a.
I'm very new on Haskell, and I'm trying the following:
To obtain [1,2,3] from [[1,2,3],[4,5,6]]?
example :: [[a]] -> [a]
example [] = []
example [x:xs] = [x]
This example is returning [1] when input is [[1,2,3]] and if I add an other element in the main List, like [[1,2,3],[3,4,5]] then I have a Non-exhaustive pattern function.
You are quite close. In fact what you here want is some sort of "safe" head.
A list [a] has two constructors:
the empty list [], you cover this in the first case; and
the "cons" (x:xs).
It looks like you cover that in the second case, but in fact you do not: you put the pattern within square brackets. As a result, Haskell interprets your pattern as [(x:xs)]. So it thinks you match a singleton list (a list with one element), and that x is the head of the sublist, and xs the tail of the sublist.
In fact you want to cover (x:xs). If we use this pattern, there is another problem: x is the head of the list, so it has type [a]. Therefore we should return x, not [x], since in the latter case, we would wrap the sublist back in a list.
So a correct function is:
example :: [[a]] -> [a]
example [] = []
example (x:_) = x -- round brackets, x instead of [x]
Note that since we are not interested in the tail here, we use an underscore _. If you compile with all warnings (-Wall, or more specific -Wunused-matches) Haskell will otherwise complain about the fact that you declare a variable that you do not use.
Generalizing to a safeHead function
We can generalize this to some sort of generic safeHead :: b -> (a -> b) -> [a] -> b function:
safeHead :: b -> (a -> b) -> [a] -> b
safeHead d _ [] = d
safeHead _ f (x:_) = f x
Here we thus pass three arguments to safeHead: a value (of type b) we should return in case the list is empty; a function to post-process the head (type a -> b), and the list to process. In that case the example is equivalent to:
example :: [[a]] -> [a]
example = safeHead [] id
But we can also return a Maybe [a] here:
example2 :: [a] -> Maybe a
example2 = safeHead Nothing Just
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 need to prototype a function, saying toList, which takes a list as its only argument, and returns a list of lists (whose type is the same that the original list).
For example [Char] will give us a [[Char]].
I've tried :
(List a) => a -> [a]
which can't work as the Class List does not exist.
How should I do then ?
Thanks in advance
Try this:
f :: [a] -> [[a]]
Tails is a good example of this:
tails :: [a] -> [[a]]
Usage:
tails [1,2,3] == [[1,2,3], [2,3], [3],[]]