So I'm really new to Haskell and have a definition called:
x :: [(char,Int)]
x needs to get defined as a function that just puts the chars (x,y,z) together with (1,2,3) in every way.
So when I call x I just want to get the output of [x,1], [x,2], [x,3], [y,1], [y,2] and so on.
Might be some easy problem but I'm confused that there is no actual input in the x function. It just needs to output the lists.
I have tried creating both lists (the number and char list) but how do I put them together in the function ?
x is not a function; it's a list of tuples. You can define it directly, or you can define a function of type foo :: [Char] -> [Int] -> [(Char, Int)], then set x by calling foo with two appropriate lists.
foo :: [Char] -> [Int] -> [(Char, Int)]
foo chars ints = ... -- You define this
x :: [(Char, Int)]
x = foo ['x', 'y', 'z'] [1, 2, 3]
As for how you define foo, I suggest you start by reading about list comprehensions. They are not the only way to define foo, but they are probably the simplest. If you are familiar with list comprehensions in a language like Python, you shouldn't have a problem; Haskell is where Python got the idea.
Related
I'm fairly new to Haskell and functional programming in general.
This seems like such a simple problem but I'm struggling with the syntax.
I want to take a list of ints as input, if it is null return a null list, and if it is not null then use the map function to add five to every element.
This is my code so far but it produces lots of errors. Any suggestions?
addFive :: [a] -> [a]
addFive [] = []
addFive a = map(+5)
You can use
addFive = map (+5)
or
addFive a = map (+5) a
As map works on empty list, explicit implementation for empty list is not required.
You are thinking along the right lines, but there are a couple of issues.
The code you have shown will complain about a type error. This is because the type of map (+5) is [a] -> [a], but you want just [a]. To fix this you just need to change that line to
addFive a = map (+5) a
Look at the types and think about why this works.
You may also have tried this:
addFive :: [a] -> [a]
addFive [] = []
addFive = map(+5)
This gives you a different error because every version of a function like this needs to have the same number of arguments. Your null case takes one argument, so the other one has to take an argument too.
However you don't need the null case. map already has that built in. So what you actually need is
addFive :: [a] -> [a]
addFive = map (+5)
By the way, one stylistic point. In Haskell we use a, b etc for type variables, but x, xs, y etc for value variables. So the version above would be more idiomatic with
addFive xs = map (+5) xs
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!
All I'm trying to do is sum a list of lists. Example of what I want to do:
Input: [[1,2,3],[2,5],[6,7]]
Output: [6,7,13]
The amount of lists inside the outer list can vary, and the amount of integers in each inner list can vary. I've tried a multitude of things, and this is the last one I tried but it doesn't work:
sumSubsets [[x]] = map sum [[x]]
Also, I wanted a base case of sumSubsets [] = [[]] but that causes errors as well. Any help would be appreciated.
You could use
sumSubsets x = map sum x
or even
sumSubsets = map sum
Your previous code,
sumSubsets [[x]] = map sum [[x]]
First performs a pattern match using [[x]] which matches a list containing a single element, which is itself a list containing a single element. Therefore it would work correctly on [[3]]
>> sumSubsets [[3]]
[3]
but not on [[1,2,3]] or [[1],[2]].
I think your problem stems primarily from mixing up types and values, which can happen easily to the beginner, in particular on lists. The whole confusion probably comes from the fact that in Haskell, [] is used as a data constructor as well as a type constructor.
For example, [Int] means "a list of Ints" (a type), but [1] means "the list that contains one element, namely the number 1" (a value -- meaning, the whole list is the value). Both things together:
xs :: [Int]
xs = [1]
When you write polymorphic functions, you abstract from something like the Int. For example, if you want to get the first element of a list, you can define a function that does that for any kind of list -- may they be lists of integers or lists of characters or even lists of lists:
firstElement :: [a] -> a
firstElement (x:xs) = x
[a] means "a list with elements of type a" (a type), and the a alone means "something of type a". firstElement is a function from a list with elements of type a to something of type a. a is a type variable. Since you're not saying what a should be, the function works for all kinds of lists:
*Main> firstElement [1,2,3]
1
*Main> firstElement ['a','b']
'a'
*Main> firstElement [[1,2],[3,4]]
[1,2]
When you wrote [[x]] you were perhaps thinking of the type of the first argument of the function, which would be a list of lists of elements of some type x (x is a type variable). You can still use that, but you have to put it into the type signature of your function (the line that contains the double colon):
sumSubsets :: Num a => [[a]] -> [a]
sumSubsets xs = map sum xs
I've used a here instead of x, since it's more commonly done, but you could use x, too. Unfortunately, the whole thing gets a bit complicated with the Num a which describes additional requirements on the type a (that it belongs to the numbers, since for other things, sum is not defined). To simplify matters, you could write:
sumSubsetsInts :: [[Int]] -> [Int]
sumSubsetsInts xs = map sum xs
I know about the length function, but if I have a list such as [(1,2),(2,3),(3,4)] and try to use length it does not work. I tried to concatenate but that doesn't help. Any idea how?
While the sensible solution to your immediate problem is (2 *) . length, as 9000 pointed out, it is worth dwelling a bit on why length [(1,2),(2,3),(3,4)] doesn't do what you expect. A Haskell list contains an arbitrary number of elements of the same type. A Haskell pair, however, has exactly two elements of possibly different types, which is something quite different and which is not implicitly converted into a list (see this question for further discussion of that point). However, nothing stops us from writing a conversion function ourselves:
pairToList :: (a, a) -> [a]
pairToList (x, y) = [x, y]
Note that the argument of pairToList is of type (a, a); that is, the function only accepts pairs with both elements having the same type.
Given pairToList, we can convert the pairs in your list...
GHCi> map pairToList [(1,2),(2,3),(3,4)]
[[1,2],[2,3],[3,4]]
... and then proceed as you planned originally:
GHCi> (length . concat . map pairToList) [(1,2),(2,3),(3,4)]
6
The concatMap function combines map and concat into a single pass...
GHCi> :t concatMap
concatMap :: Foldable t => (a -> [b]) -> t a -> [b]
... and so your function becomes simply:
GHCi> (length . concatMap pairToList) [(1,2),(2,3),(3,4)]
6
length [(1,2),(2,3),(3,4)] gives you 3 because there are precisely three elements in the list where the elements are tuples, each consisting of two integers. use this function to get all the "elements"
tupleLength :: [(Int, Int)] -> Int
tupleLength = (*2) . length
In The Little Schemer there is a function to check, whether the list is flat:
(define lat?
(lambda (l)
(cond
((null? l) #t)
((atom? (car l)) (lat? (cdr l)))
(else #f))))
I'm trying to write the same recursive function in Haskell, but have no success:
is_lat :: [a] -> Bool
is_lat [] = True
is_lat ???
How do i check that the parameter is not in the form [[a]]? In other words, [1,2,3] is a valid input, but [[1,3], [2,4]] and [[[1,2,3]]] aren't.
I want to use this further in recursive functions that accept lists to make sure that i deal with flat lists only.
EDIT: I see that people are confused because of the is_lat :: [a] -> Bool type signature. I agree now, that i shouldn't check type on runtime. However, is it possible to check the type on compile-time? How can i make the function work only for flat lists? Or should i completely change my way of thinking?
You can't really think of nested lists the same way in Haskell as in Scheme, because they're not the same data structure. A Haskell list is homogenous, where as a Lisp "list" is actually closer to a rose tree (as pointed out by C.A.McCann below). As an illustrative example, take a look at how the WYAS48 parsing section defines LispVal.
If you really, really, really want to do runtime type checking, even though it's usually a bad idea and very unconventional in Haskell, look into Data.Typeable. This response might be useful too.
The real answer to this question is "You need to think about your arguments differently in Haskell than in Lisp, which results in never needing to perform this check yourself at runtime" (and I say this as a Common Lisper, so I understand how frustrating that is to start with).
Addendum: In response to your edit, Haskell's type system automatically ensures this. If you have a function of type foo :: [Int] -> Int, for example, and you pass it ["One", "Two", "Three"] or [[1, 2, 3]], you'll get a compile-time error telling you what just exploded and why. If you want to specialize a function, just declare a more specific type.
For instance (don't write code like this, it's just for illustrative purposes), say you have a simple function like
myLookup index map = lookup index map
If you load this into GHCi and run :t myLookup, it'll tell you that the functions' type is myLookup :: Eq a => a -> [(a, b)] -> Maybe b which means that it can take a key of any type that derives Eq (anything you can run == on). Now, say that for whatever reason you want to ensure that you only use numbers as keys. You'd ensure that by adding a more specific type declaration
myLookup :: Int -> [(Int, a)] -> Maybe a
myLookup index map = lookup index map
Now, even though there's nothing in the body of the function preventing it from dealing with other key types, you'll get a type error at compile time if you try to pass it something other than an Int index or something other than an [(Int, a)] map. As a result, this
myLookup :: Int -> [(Int, a)] -> Maybe a
myLookup ix lst = lookup ix lst
main :: IO ()
main = putStrLn . show $ myLookup 1 [(1, "Foo")]
will compile and run fine, but this
myLookup :: Int -> [(Int, a)] -> Maybe a
myLookup ix lst = lookup ix lst
main :: IO ()
main = putStrLn . show $ myLookup "Nope.jpg" [("Foo", 1)]
will do neither. On my machine it errors at compile time with
/home/inaimathi/test.hs:5:35:
Couldn't match expected type `Int' with actual type `[Char]'
In the first argument of `myLookup', namely `"Nope.jpg"'
In the second argument of `($)', namely
`myLookup "Nope.jpg" [("Foo", 1)]'
In the expression:
putStrLn . show $ myLookup "Nope.jpg" [("Foo", 1)]
Failed, modules loaded: none.
I really hope that didn't confuse you further.
This is both impossible and unnecessary with standard Haskell lists because Haskell is strongly typed; either all elements of a list are themselves lists (in which case the type is [a] = [[b]] for some b), or they are not.
E.g. if you try to construct a mixed list, you will get an error from the compiler:
Prelude> ["hello", ["world!"]]
<interactive>:3:12:
Couldn't match expected type `Char' with actual type `[Char]'
In the expression: "world!"
In the expression: ["world!"]
In the expression: ["hello", ["world!"]]
The function type [a] -> Bool implicitly means forall a. [a] -> Bool, in other words it's defined identically for lists of all possible element types. That does include types like [[Int]] or [[[String]]] or any depth of nesting you can think of. But it doesn't--and can't--matter to your function what the element type is.
As far as this function is concerned, the input is always a list whose elements are some opaque, unknown type. It will never receive nested lists containing that same opaque type.
Well, I guess, in Haskell you are limited to http://ideone.com/sPhRCP:
main = do -- your code goes here
print $isFlat [Node 1, Node 2, Node 3]
print $isFlat [Node 1, Node 2, Branch [Node 3, Node 4, Node 5], Node 6]
data Tree a = Node a | Branch [Tree a]
isFlat :: [Tree a] -> Bool
isFlat = all isNode where
isNode (Node _) = True
isNode _ = False
In non strictly-typed languages every object has run-time type information and thus can be polymorphic. This might be a complicated network of coercions, like in Scala (less complicated if you're in C++), or just "everything is an object, and object is everything" like in purely dynamic languages (Lisp, JS, ...).
Haskell is strictly-typed.