Related
Can someone please explain how I can fix my program.
Very new to Haskell, been trying to create a length function that calculates the length of a list of any type.
I am aiming to do this using data as I want to create a brand new type to do so (this is the area of Haskell that I'm currently learning, which is why it might not be the most efficient implementation of this function)
data List a = Nil | Cons a (List a)
len :: List a -> Int
len Nil = 0
len (Cons _ xs) = 1 + len xs
If I run it on len [1,2,3]
I get the error:
• Couldn't match expected type ‘List a0’
with actual type ‘[Integer]’
• In the first argument of ‘len’, namely ‘[1, 2, 3]’
In the expression: len [1, 2, 3]
In an equation for ‘it’: it = len [1, 2, 3]
The function definition is correct, but [1,2,3] is not a List a object, it is a [a] (or more canonical [] a). A list like [1,2,3] as List Int is:
len (Cons 1 (Cons 2 (Cons 3 Nil)))
Alternatively, you can make List a an instance of the IsList type class, and then use the -XOverloadedLists extension:
{-# LANGUAGE TypeFamilies #-}
import GHC.Exts(IsList(Item, fromList, toList))
instance IsList (List a) where
type Item (List a) = a
fromList = foldr Cons Nil
toList Nil = []
toList (Cons x xs) = x : toList xs
Then we can use the OverloadedLists extension:
$ ghci -XOverloadedLists -XTypeFamilies
GHCi, version 8.0.2: http://www.haskell.org/ghc/ :? for help
Loaded GHCi configuration from /home/kommusoft/.ghci
Prelude> data List a = Nil | Cons a (List a)
Prelude> import GHC.Exts(IsList(Item, fromList, toList))
Prelude GHC.Exts> :{
Prelude GHC.Exts| instance IsList (List a) where
Prelude GHC.Exts| type Item (List a) = a
Prelude GHC.Exts| fromList = foldr Cons Nil
Prelude GHC.Exts| toList Nil = []
Prelude GHC.Exts| toList (Cons x xs) = x : toList xs
Prelude GHC.Exts| :}
Prelude GHC.Exts> :{
Prelude GHC.Exts| len :: List a -> Int
Prelude GHC.Exts| len Nil = 0
Prelude GHC.Exts| len (Cons _ xs) = 1 + len xs
Prelude GHC.Exts| :}
Prelude GHC.Exts> len [1,2,3]
3
Let's say I have the following input:
[(0, [1, 2]) , (2, [3, 4]) , (4, [])
This is an adjacency list and I want to convert it as such:
[(0,1), (0,2), (2,3), (2, 4)] -- notice how there is no 4 mapping to anything
Here is what I have so far:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv adj = map fn adj -- mapping (0, [1, 2]) should give me [(0, 1), (0, 2)]
fn:: (Int, [Int]) -> [(Int, Int)]
fn (rt, list) = -- somehow perform [(rt, l[0]), (rt, l[1]) ...]
List comprehension can do the trick:
conv :: [(a, [b])] -> [(a, b)]
conv xys = [(x, y) | (x, ys) <- xys, y <- ys ]
Or we can use concatMap here:
conv :: Foldable f => f (a, [b]) -> [(a, b)]
conv = concatMap (uncurry (map . (,)))
Here the inner function uncurry (map . (,)) takes a tuple (x, ys) and thus performs a map (x,): the uncurry basically unpacks the tuple (x, ys), and calls (map . (,)) x ys, so that means that we obtain (map (x,)) ys. The above syntax uses the TupleSections extension, but we do not need to activate that extension in the real program, since we never write such syntax. Your fn function you defined is thus equivalent to uncurry (map . (,)).
We thus use this function in a concatMap that will pass the 2-tuples, and concatenate the lists these individual tuples create.
or we can use the "bind" >>= :: Monad m => m a -> (a -> m b) -> m b function:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (\(x, ys) -> ys >>= return . (x,))
or shorter:
conv :: Monad m => m (a, m b) -> m (a, b)
conv = (=<<) (uncurry (fmap . (,)))
the nice thing about the latter is that it also works with Maybes, etc. For example:
Prelude> conv [(0, [1, 2]) , (2, [3, 4]) , (4, [])]
[(0,1),(0,2),(2,3),(2,4)]
Prelude> conv Nothing
Nothing
Prelude> conv (Just (3, Nothing))
Nothing
Prelude> conv (Just (3, Just 2))
Just (3,2)
Taking advantage of instance Traversable ((,) a), we have this remarkably short (and remarkably inscrutable) solution:
conv :: [(Int, [Int])] -> [(Int, Int)]
conv = (sequence =<<)
The most general type of (sequence =<<) is (Monad m, Traversable t) => m (t (m a)) -> m (t a).
In Data.List module there's inits function that turns for example, [1,2,3,4] -> [[],[1],[1,2],[1,2,3],[1,2,3,4]]
I'm trying to define similar function using recursion, however I can't think of a way doing in correct order. The closest I have gotten is the list backwards, result = [[],[4],[3,4],[2,3,4],[1,2,3,4]]:
inits' :: [Int] -> [[Int]]
inits' [] = [[]]
inits' (x:xs) = inits' xs ++ [(x:xs)]
I'm not exactly sure how I could create a list by appending one element at time in the correct order? Could someone point in right direction, or is it not possible to do via recursion?
The easiest thing to try for such a function is just looking at the desired result and “reverse-pattern-matching” on the RHS of the function equation.
You already have that with
inits' [] = [[]]
Now with inits (x:xs), for example inits (1:[2,3,4]), you know that the result should be [[],[1],[1,2],[1,2,3],[1,2,3,4]], which matches the pattern []:_. So
inits' (x:xs) = [] : _
Now, the simplest recursion would be to just call inits' again on xs, like
inits' (x:xs) = [] : inits' xs
however, that doesn't give the correct result: assuming the recursive call works correctly, you have
inits' (1:[2,3,4]) = [] : [[],[2],[2,3],[2,3,4]]
= [[],[],[2],[2,3],[2,3,4]]
The 1 is completely missing, obviously, because we didn't actually use it in the definition. We need to use it, in fact it should be prepended before all of the list-chunks in the recursive result. You can do that with map.
We can prepend the data of all the remaining inits, like for example:
inits' :: [a] -> [[a]]
inits' [] = [[]]
inits' (x:xs) = [] : map (x:) (inits' xs)
As a basecase we return a singleton list with an empty list when the input is an empty list.
In the recursive case, we first yield the empty list, followed by the inits' of the tail of the list, but all these elements are prepended with x (with map (x:)).
Then we have:
Prelude> inits' [1,4,2,5]
[[],[1],[1,4],[1,4,2],[1,4,2,5]]
Since (not in evaluation order):
inits' [1,4,2,5]
-> [] : map (1:) (inits' [4,2,5])
-> [] : map (1:) ([] : map (4:) (inits' [2,5]))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) (inits' [5])))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) ([] : map (5:) (inits' []))))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) ([] : map (5:) [[]])))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) ([] : [[5]])))
-> [] : map (1:) ([] : map (4:) ([] : map (2:) [[],[5]]))
-> [] : map (1:) ([] : map (4:) ([] : [[2],[2,5]]))
-> [] : map (1:) ([] : map (4:) [[],[2],[2,5]])
-> [] : map (1:) ([] : [[4],[4,2],[4,2,5]])
-> [] : map (1:) [[],[4],[4,2],[4,2,5]]
-> [] : [[1],[1,4],[1,4,2],[1,4,2,5]]
-> [[],[1],[1,4],[1,4,2],[1,4,2,5]]
I think you should change your function definition from:
inits' :: [Int] -> [[Int]]
to:
inits' :: [a] -> [[a]]
Since inits from Data.List is of type [a] -> [[a]], and it doesn't care whats actually in the list. It needs to be polymorphic and accept a list of any type.
Furthermore, since others have shown the most straightforward recursive approach, you can also use foldr here.
Here is the base code:
inits' :: [a] -> [[a]]
inits' = foldr (\x acc -> [] : (map (x:) acc)) [[]]
Where [[]] is the base case, just like in your function. For the actual recursive part, here is how it works with the call inits' [1, 2, 3, 4]:
Starts folding from the right at value 4, and creates [[], [4]]
Now on value 3, and creates [[], [3], [3, 4]
Now on value 2, and creates [[], [2], [2, 3], [2, 3, 4]]
Now on value 1, and creates [[], [1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
Which gives the final nested list required, similarily to the function call:
*Main> inits' [1,2,3,4]
[[],[1],[1,2],[1,2,3],[1,2,3,4]]
From the behavior described above, you just need to focus on [] : (map (x:) acc), where you map the current value x being folded into your accumulated list acc, while also prepending an empty list on each fold.
If you still have trouble understanding foldr, you can look at this minimal example of how the folding performs from the right:
foldr f x [a, b, c] = a `f` (b `f` (c `f` x))
and How does foldr work?
Consider the list of lists
thisList = [[1], [1, 1], [1, 1, 1]]
how could I multiple thisList so that it would produce another list
anotherList = [[1], [2, 2], [3, 3, 3]]
I have made the function
reps = [1] : map (\ns -> head ns:ns) reps
which produces thisList
Thanks for any help
You could do:
zipWith (\x -> map (const x)) [1..] thisList
Example usage:
Prelude> let thisList = [[1], [1,1], [1,1,1]]
Prelude> zipWith (\x -> map (const x)) [1..] thisList
[[1],[2,2],[3,3,3]]
Or simpler:
zipWith (map . const) [1..] thisList
It's quite easy. zipWith f as bs is equivalent to map (uncurry f) $ zip as bs. So we have:
zip [1..] thisList == [(1, [1]), (2, [1,1,]), (3, [1,1,1])]
Then we apply f to each pair and so:
map (const 1) [1] == [const 1 1] == [1]
map (const 2) [1,1] == [const 2 1, const 2 1] == [2,2]
map (const 3) [1,1,1] == [const 3 1, const 3 1, const 3 1] == [3,3,3]
If you meant that a sublist of length n should be replaced by [n, n, ..., n] of length n, as in:
thisList = [[1, 1], [1], [1], [1, 1, 1]]
result = [[2,2], [1], [1], [3,3,3]]
then you have to change approach:
map (\xs -> let len = length xs in replicate len len) thisList
Example:
Prelude> let thisList = [[1, 1], [1], [1], [1, 1, 1]]
Prelude> map (\xs -> let len = length xs in replicate len len) thisList
[[2,2],[1],[1],[3,3,3]]
I am a relative haskell newbie and am trying to create a list of tuples with an equation I named splits that arises from a single list originally, like this:
splits [1..4] --> [ ([1],[2,3,4]), ([1,2],[3,4]), ([1,2,3],[4]) ]
or
splits "xyz" --> [ ("x","yz"), ("xy","z") ]
Creating a list of tuples that take 1, then 2, then 3 elements, etc. I figured out I should probably use the take/drop functions, but this is what I have so far and I'm running into a lot of type declaration errors... Any ideas?
splits :: (Num a) => [a] -> [([a], [a])]
splits [] = error "shortList"
splits [x]
| length [x] <= 1 = error "shortList"
| otherwise = splits' [x] 1
where splits' [x] n = [(take n [x], drop n [x])] + splits' [x] (n+1)
The Haskell-y approach is to use the inits and tails functions from Data.List:
inits [1,2,3,4] = [ [], [1], [1,2], [1,2,3], [1,2,3,4] ]
tails [1,2,3,4] = [ [1,2,3,4], [2,3,4], [3,4], [4], [] ]
We then just zip these two lists together and drop the first pair:
splits xs = tail $ zip (inits xs) (tails xs)
or equivalently, drop the first element of each of the constituent lists first:
= zip (tail (inits xs)) (tail (tails xs))
splits [] = []
splits [_] = []
splits (x:xs) = ([x], xs) : map (\(ys, zs) -> (x:ys, zs)) (splits xs)
You have several mistakes.
You don't need to have Num a class for a.
use [] or [x] as pattern, but not a variable, use xs instead.
Use ++ instead of + for concatenating lists.
In our case use (:) to add list to value instead of ++.
Add stop for recursion, like additional variable maxn to splits'
splits :: [a] -> [([a], [a])]
splits [] = error "shortList"
splits xs
| lxs <= 1 = error "shortList"
| otherwise = splits' xs 1 lxs
where
lxs = length xs
splits' xs n maxn
| n > maxn = []
| otherwise = (take n xs, drop n xs) : splits' xs (n+1) maxn
There is a built in function that kind of does a part of what you want:
splitAt :: Int -> [a] -> ([a], [a])
which does what it looks like it would do:
> splitAt 2 [1..4]
([1,2],[3,4])
Using this function, you can just define splits like this:
splits xs = map (flip splitAt xs) [1..length xs - 1]