In an attempt to learn how haskell works, I created the following statements. I am trying to understand what their types are; can anybody let me know if I am the right track?
statement type
['h', 'e', 'l', 'l', 'o'] ['h', 'e', 'l', 'l', 'o'] :: [char]
[(9,8),(7,6),(5,4)] [(9,8),(7,6),(5,4)] :: [int a, int b] => [(a,b)]
if that's correct, can someone help me understand the type / function for these statements:
even x = x 'mod' 1 == 1
chart x y = [y| x <- [1..x]]
Your type signatures are not quite correct. Pay attention to capitalisation, it's [Char]; and it's Num and not int; and also wrong brackets: (Num a, Num b) => [(a, b)]. As for the rest...
$ ghci
[...]
Prelude> let even x = x `mod` 1 == 1
Prelude> :t even
even :: Integral a => a -> Bool
Prelude> let chart x y = [y| x <- [1..x]]
Prelude> :t chart
chart :: (Enum t1, Num t1) => t1 -> t -> [t]
Also, note the backticks on the mod, not quotes.
EDIT following the comments:
It seems that you also want the clarification on the meaning of the functions even and chart.
Even of x is the value of whether the remainder when you divide x by one is one
Unfortunately, the function is incorrectly written, since all integers are divisible by 1, and the remainder is never 1. The correct definition for even is
even x = x `mod` 2 == 0
Even of x is the value of whether the remainder when you divide x by two is zero
As for chart,
Chart of a value x and a number y is a list consisting of values y for each element in a list of numbers from 1 to x
so if you do chart 3 5, you will have a list of threes for each element in [1, 2, 3, 4, 5], so five threes: [3, 3, 3, 3, 3]
Types in Haskell are capitalized; yes, it matters.
['h', 'e', 'l', 'l', 'o'] :: [Char]
Correct, although [Char] and String are type synonyms, and String looks nicer. :P
[(9,8),(7,6),(5,4)] :: (Num a, Num b) => [(a,b)]
Multiple constraints are in round brackets. There's no "int" typeclass.
even x = x `mod` 1 == 1
even :: Integral a => a -> Bool
Make sure you use backticks and not single quotes; yes, it matters. In ghci use :t to check the type of mod and (==), and use :i to check the relationship between Num and Integral, and you should be able to put this together.
chart x y = [y | x <- [1..x]]
chart :: (Num a, Enum a) => a -> b -> [b]
For this, you have to know the "long name" of [a..b] is enumFromTo, as well as how to desugar list comprehensions. List comprehensions aren't hard, but there's already good descriptions in RWH, LYAH, and the Haskell 2010 Report, so I won't leave one here.
Related
I have a list with the type `[(Int, Char, Int)]'. E.g:
[(1, 'x', 1), (1, 'y', 2), (2, 'x', 1)]
The first Int is the number of times the Char appears and the second Int is to differentiate the same char from each other. For example, there could be x1 and x2.
I want to join elements of that list that have the same 2nd and 3rd element. In the case of the list above, it would become [(3, 'x', 1), (1, 'y', 2)] (the first and third tuples from the initial list were added together).
I've looked into zipWith and list comprehensions, but none of them seem to work. Is there any other way that I'm not thinking about that might work here?
The two functions you want to use are Data.List.sortBy and Data.List.groupBy.
If we sort by comparing the second and third elements of each tuple, we get the entries in the list sorted by variable and exponent. This is accomplished by passing a lambda which uses pattern macthing to extract and compare just those elements.
import Data.List
lst = [(1, 'x', 1), (1, 'y', 2), (2, 'x', 1)]
lst' = sortBy (\(_, a, b) (_, a', b') -> (a,b) `compare` (a',b')) lst
-- [(1,'x',1), (2,'x',1), (1,'y',2)]
Now we need to group based on the second and third values. groupBy will not work the way you need on an unsorted list, so don't skip that step.
The lambda being passed to groupBy here should look very familiar from the previous example.
lst'' = groupBy (\(_, a, b) (_, a', b') -> a == a' && b == b') lst'
-- [[(1,'x',1), (2,'x',1)], [(1,'y',2)]]
Now summing the first elements of the tuples and incorporating the other information is trivial with list comprehensions.
We get the variable and exponent info from the first element in the list and bind those to x and y respectively, then sum up the first coefficients and build a new tuple.
[let (_,x,y) = lst!!0 in (sum [c | (c,_,_) <- lst], x, y) | lst <- lst'', not (null lst)]
-- [(3,'x',1), (1,'y',2)]
First of all, I would suggest working with more meaningful domain types. A 3-tuple of built-in types could mean a lot of different things. By defining a new type and naming the components, you make everything clearer and prevent mistakes like getting the two Ints mixed up:
type Power = Int
type Coefficient = Int
data Exp var = Exp var Power deriving (Show, Eq, Ord)
data Term var = Term Coefficient (Exp var) deriving Show
What you're doing looks a lot to me like combining terms in polynomials, so I've defined types that make sense in that context. You may prefer different names, or a different structure, if you're actually doing something else.
Now you're looking for a function of type [Term Char] -> [Term Char], which groups together like Exps. Generally Data.Map.fromListWith is a great tool for grouping list items together by a key:
import qualified Data.Map as M
combine :: Ord a => [Term a] -> M.Map (Exp a) Coefficient
combine = M.fromListWith (+) . map toTuple
where toTuple (Term coef exp) = (exp, coef)
Then all that's left is to re-inflate the Map we've extracted to a list again:
simplify :: Ord a => [Term a] -> [Term a]
simplify = map fromTuple . M.assocs . combine
where fromTuple (exp, coef) = Term coef exp
And indeed, we get the grouping you hoped for:
*Main> simplify [Term 1 (Exp 'x' 1), Term 1 (Exp 'y' 2), Term 2 (Exp 'x' 1)]
[Term 3 (Exp 'x' 1),Term 1 (Exp 'y' 2)]
insert_at insert an element e into a list xs in specific location n
testgetting Left if n less than 0
test2 getting Left if n larger than xs's length or The type e isn't match the element's type in listxs. Otherwise passing Right xs to the next.
import Data.Typeable
insert_at :: a -> [a] -> Int -> [a]
insert_at e xs n = a++(e:b) where
t = splitAt n xs
a = fst t
b = snd t
test :: (Ord a, Num a) => b -> a -> Either [Char] b
test xs n = if n < 0 then Left "n<0" else Right xs
test2 :: (Typeable a1, Typeable a2) =>
a1 -> [a2] -> Int -> Either [Char] [a2]
test2 e xs n
| n> ( length xs )= Left "n> $ length xs "
| (typeOf e) /= (typeOf (head xs) ) = Left "(typeOf e) /= (typeOf (head xs) ) "
|otherwise = Right xs
sf :: Typeable a => a -> [a] -> Int -> Either [Char] [a]
sf e xs n = test xs n >>test2 e xs n >> Right (insert_at e xs n)
All the other error got properly handled, expect this.
* No instance for (Num Char) arising from the literal `1'
* In the expression: 1
In the second argument of `sf', namely `[1, 2, 3, 4, ....]'
In the expression: sf 'a' [1, 2, 3, 4, ....] 3
The error message states that you're trying to evaluate the expression sf 'a' [1, 2, 3, 4, ....] 3. Since this expression is not shown in your question, I'm assuming you're using it in GHCi to test out your code, right?
The type signature of sf says that the first parameter has type a, and the second parameter has type [a], which is a list whose elements are of the same type as the first parameter.
So the compiler sees that the first parameter is 'a'. That's a character, type Char.
"Got it," - thinks the compiler, - "now I know that a is Char. And now I know that the second parameter must have type [Char] - that is, a list of Char".
And yes, the second parameter is indeed a list, but wait! The first element of the list is not a character, but number 1! That does not compute!
Fortunately, number literals are special in Haskell. Number literals are not merely of type Int or even of type Integer, no! Numbers can be of any type as long as that type has an instance of class Num.
So since the compiler already knows that the elements of that list must be of type Char, but it sees a number literal, it concludes that it must now find an instance of class Num for type Char.
But there is no such instance! And so the compiler rightly complains: "no instance Num Char"
To fix the problem, I need to better understand what you were actually trying to do.
Did you intend the whole function to work on numbers? Then the first parameter must be a number, not a character.
Or did you intend it to work on characters? Then the second parameter must be a list of characters, not numbers.
Or did you intend the first two parameters not to be the same type at all? Then you must change the type signature of sf to indicate that.
sf expects a value and a list as its first two arguments. The elements of the list must have the same type as the first argument. This is the meaning of
sf :: a -> [a] -> ...
When you write sf 'a' [1], this means 1 and 'a' must have the same type. So the type checker looks for a way to interpret 1 as a Char; it fails, because this is not possible. Some fixes might include:
sf 'a' "1234" 3
sf 'a' [toEnum 1, toEnum 2, toEnum 3, toEnum 4] 3
sf (fromEnum 'a') [1, 2, 3, 4] 3
I am teaching myself Haskell, and playing with list comprehensions. I wrote this list comprehension:
[ c | a <- [1..3], b <- [1..4], let c = hyp a b, c == round c]
I hoped it would produce the list of values c where c is an integer (c == round c), which would be only 5, but it does not compile. Playing around some more, I've found I can't really embed any functions in a list comprehension, I'm sure there is a way, I just don't know how.
Here's the error code:
<interactive>:158:1: error:
• Ambiguous type variable ‘t0’ arising from a use of ‘it’
prevents the constraint ‘(Floating t0)’ from being solved.
Probable fix: use a type annotation to specify what ‘t0’ should be.
These potential instances exist:
instance Floating Double -- Defined in ‘GHC.Float’
instance Floating Float -- Defined in ‘GHC.Float’
• In the first argument of ‘print’, namely ‘it’
In a stmt of an interactive GHCi command: print it
Thanks!
First of all, include necessary definitions in a question like this.
hyp :: Floating a => a -> a -> a
hyp a b = sqrt $ a^2 + b^2
Now. You can “embed” functions all right in list comprehensions. Apparently you just chose some unfortunate ones! round has the following type:
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> :t round
round :: (Integral b, RealFrac a) => a -> b
So, for round c == c to make sense, you'd need to have a number type that's both an instance of Integral and of RealFrac. In other words, this type would contain fractions, yet all its elements would be integers†. Well, you can't have your cake and eat it too!
This problem would have been much more evident, like so often in Haskell, if you had actually written out some type signatures. While fooling around like that, it often helps to just select some simple example type. Perhaps the most reasonable thing would seem:
Prelude> [ c | a <- [1..3], b <- [1..4], let c = hyp a b, c == round c] :: [Integer]
<interactive>:6:41:
No instance for (Floating Integer) arising from a use of ‘hyp’
In the expression: hyp a b
In an equation for ‘c’: c = hyp a b
In the expression:
[c |
a <- [1 .. 3], b <- [1 .. 4], let c = hyp a b, c == round c] ::
[Integer]
Ok, so Integer doesn't work because you're trying to do real arithmetic, with those square roots in hyp. This is not possible with Integer, you need a Floating type like Double. Let's try that:
Prelude> [ c | a <- [1..3], b <- [1..4], let c = hyp a b, c == round c] :: [Double]
<interactive>:8:55:
No instance for (Integral Double) arising from a use of ‘round’
In the second argument of ‘(==)’, namely ‘round c’
In the expression: c == round c
In a stmt of a list comprehension: c == round c
Ok, this is because as I said, round always gives integral-type results. However, you can always convert such an integral type to a Double again:
Prelude> [ c | a <- [1..3], b <- [1..4], let c = hyp a b, c == fromIntegral (round c)] :: [Double]
[5.0]
Note that this is not really a good solution though: you don't really want the result to be floating point if you go already check that the elements are really integral! I'd recommend in this case not just evaluating hyp as such at all. Better use this comprehension:
Prelude> [ c | a <- [1..3], b <- [1..4], let c² = a^2 + b^2; c = round . sqrt $ fromIntegral c², c^2==c²] :: [Integer]
[5]
One big argument for this version is that it does the comparison in Integer, not in Double. Floating-point equality comparison is something you should best stay away from entirely if you can help it; in this case it's mostly harmless because the interesting thing is the integer subset, which can in fact be represented exactly (unlike decimal fractions like 0.1). Still you ca get wrong results this way: in particular, for sufficiently large floating-point numbers, c == fromInteger (round c) will always be true, because above a certain threshold all values are integral after all.
Prelude> [ c | a <- take 4 [1000000000000..], b <- take 5 [1000000000000..], let c = hyp a b, c == fromIntegral (round c)] :: [Float]
[1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12,1.4142135e12]
But none of these are actually correct integral hypothenuses, as you can see with the version that does the comparison in Integer:
Prelude> [ c | a <- take 4 [1000000000000..], b <- take 5 [1000000000000..], let c² = a^2 + b^2; c = round . sqrt $ fromIntegral c², c^2==c²] :: [Integer]
[]
Strictly speaking, this improved version is also not safe though – it doesn't give false positives, but may not find actual Pythagorean triples because the lossy floating-point steps can already destroy equality. To do it real properly, you need an all-integral
intSqrt :: Integral a => a -> Maybe a
This could probably done quite efficiently by taking the float sqrt as a starting value for a few rounds of pseudo Newton-Raphson in integer arithmetic.
†In principle, the round function could also have a more relaxed signature.
round' :: (Num b, RealFrac a) => a -> b
round' = fromInteger . round
With that version, your original code would work.
Given a list like:
[1, 2, 2, 6, 7, 8, 10, 11, 12, 15]
Split it into blandly increasing ranges (maybe equal):
[[1, 2, 2], [6, 7, 8], [10, 11, 12], [15]]
I tried using a recursive approach:
splitRanges [] = [[]]
splitRanges (x:y:xs)
| x `elem` [y, y + 1] = [x, y] : splitRanges xs
| otherwise = xs
So if the item is one less or equal to the item after I fuse them. But it says I am trying to build an infinite type:
Occurs check: cannot construct the infinite type: a0 = [a0]
Expected type: [[a0]]
Actual type: [a0]
But what does [the fact that it is monotone] have to do with how the list is split?
That being strictly increasing would give different results.
Or are you really trying to say something else?
I hope I am not.
Will the list always be monotone?
No, splitting a monotone list means making it into just one sub-list.
If not, how should that affect the results?
If it is not monotone, you will have many sublists.
Is it always brown into groups of three?
No, the groups may contain n elements.
More examples would be good
splitRanges [1, 3] == [[1], [3]]
splitRanges [1, 2, 5] == [[1, 2], [3]]
splitRanges [0, 0, 1] == [[0, 0, 1]]
splitRanges [1, 5, 7, 9] == [[1], [5], [7], [9]]
I appreciate hints rather than full answers, as I would like to improve myself, copy-pasting is not improvement.
Try breaking the problem into more manageable parts.
First, how would you split just one blandly increasing range from the start of a list? Lets guess that should be splitOne :: [Integer] -> ([Integer], [Integer]).
Second, how can you repeatedly apply splitOne to the left-over list? Try implementing splitMany :: [Integer] -> [[Integer]] by using splitOne.
For splitOne, what should you be trying to find? The first position to split at. What are "split positions"? Lets make that up.
split 0 1 2 3 4 …
list [ | x1, | x2, | x3, | x4, | x5, …]
So a split at 0 is ([], [x1,x2,x3,x4,x5,…]), and a split at 3 is ([x1,x2,x3],[x4,x5,…]). What relationship can you see between the split position and the split list?
How do you determine the first split position of the list? Lets say that is implemented as firstSplitPos :: [Integer] -> Integer. What is the first split position of an empty list?
Can you now implement splitOne using firstSplitPos?
One Possible Answer
-- What are the adjacencies for:
-- 1) empty lists?
-- 2) lists with one element?
-- 3) lists with more than one element?
--
-- Bonus: rewrite in point-free form using <*>
--
adjacencies :: [a] -> [(a,a)]
adjacencies xxs = zip xxs (drop 1 xxs)
-- Bonus: rewrite in point-free form
--
withIndices :: [a] -> [(Int,a)]
withIndices xxs = zip [0..] xxs
-- This is the most involved part of the answer. Pay close
-- attention to:
-- 1) empty lists
-- 2) lists with one element
-- 3) lists which are a blandly increasing sequence
--
firstSplitPos :: (Eq a, Num a) => [a] -> Int
firstSplitPos xxs = maybe (length xxs) pos (find q searchList)
where q (_,(a,b)) = a /= b && a + 1 /= b
searchList = withIndices (adjacencies xxs)
-- Why is the split position one more than the index?
pos (i,_) = i + 1
--
-- Bonus: rewrite in point-free form using <*>
--
splitOne :: (Eq a, Num a) => [a] -> ([a],[a])
splitOne xxs = splitAt (firstSplitPos xxs) xxs
splitMany :: (Eq a, Num a) => [a] -> [[a]]
-- What happens if we remove the case for []?
splitMany [] = []
splitMany xxs = let (l, r) = splitOne xxs in l : splitMany r
Another Approach
This is my explanation of Carsten's solution. It is already succinct but I have elected for a variation which does not use a 2-tuple.
We know that Haskell lists are defined inductively. To demonstrate this, we can define an equivalent data type.
data List a = Cons a (List a) -- Cons = (:)
| Nil -- Nil = []
Then ask the question: can we use induction on lists for the solution? If so, we only have to solve two cases: Cons and Nil. The type signature of foldr shows us exactly that:
foldr :: (a -> b -> b) -- Cons case
-> b -- Nil case
-> [a] -- The list
-> b -- The result
What if the list is Nil? Then the only blandly increasing sequence is the empty sequence. Therefore:
nilCase = [[]]
We might want nilCase = [] instead, as that also seems reasonable — i.e. there are no blandly increasing sequences.
Now you need some imagination. In the Cons case we only get to look at one new element at a time. With this new element, we could decide whether it belongs to the right-adjacent sequence or if it begins a new sequence.
What do I mean by right-adjacent? In [5,4,1,2,2,7], 1 belongs to the right-adjacent sequence [2,2].
How might this look?
-- The rest of the list is empty
consCase new [] = [new] : []
-- The right-adjacent sequence is empty
consCase new ([]:ss) = [new] : ss
-- The right-adjacent sequence is non-empty
-- Why `new + 1 == x` and not `new == x + 1`?
consCase new sss#(xxs#(x:_):ss)
| new == x || new + 1 == x = (new:xxs):ss
| otherwise = [new]:sss
Now that we solved the Nil case and the Cons case, we are done!
splitRanges = foldr consCase nilCase
It would be useful and idiomatic to write your function to take a predicate, instead of writing your split condition into the function itself:
splitBy2 :: (a -> a -> Bool) -> [a] -> [[a]]
splitBy2 ok xs = snd $ f xs [] []
where f (a:b:xs) acc_list acc_out_lists | ok a b = ...
I hope you don't mind spoiling part of it, but as the comments are discussing what you want (and I hope I've got it) maybe you are interested in another possible solution?
I don't want to spoil it all but I think you can easily work this out:
blandly :: (Ord a, Num a) => [a] -> [[a]]
blandly = g . foldr f ([],[])
where f x ([],xss) = ([x],xss)
f x (y:ys,xss)
| abs (x-y) <= 1 = undefined
| otherwise = undefined
g (ys,xss) = undefined
you just have to fill in the undefined holes
The idea is just to fold the list from the right, accumulating your inner lists in the first item of the tuple, s long as the elements are not to far away; and if they are: to push it to the second item.
If done correctly it will yield:
λ> blandly [1,3]
[[1],[3]]
λ> blandly [1,2,5]
[[1,2],[5]]
λ> blandly [0,0,1]
[[0,0,1]]
λ> blandly [1,5,7,9]
[[1],[5],[7],[9]]
which seems to be what you want
1 hour later - I think I can post my solution - just stop reading if you don't want to get spoiled
blandly :: (Ord a, Num a) => [a] -> [[a]]
blandly = uncurry (:) . foldr f ([],[])
where f x ([],xs) = ([x],xs)
f x (y:ys,xs)
| abs (x-y) <= 1 = (x:y:ys,xs)
| otherwise = ([x],(y:ys):xs)
maybe I have a slight misunderstanding here (the examples did not specify it) - but if you want on only monotonic increasing inner lists you just have to change the abs part:
blandly :: (Ord a, Num a) => [a] -> [[a]]
blandly = uncurry (:) . foldr f ([],[])
where f x ([],xss) = ([x],xss)
f x (y:ys,xss)
| 0 <= y-x
&& y-x <= 1 = (x:y:ys,xss)
| otherwise = ([x],(y:ys):xss)
My code:
isOrdered :: (a -> a -> Bool) -> [a] -> Bool
isOrdered mark xs =(head xs) `mark`(head(tail xs))
Compiles perfectly but when I try to call it with
isOrdered < [1,2,3]
I get an error:
Couldn't match expected type `(a0 -> a0 -> Bool) -> [a0] -> Bool'
with actual type `[t0]'
In the second argument of `(<)', namely `[1, 2, 3]'
In the expression: isOrdered < [1, 2, 3]
In an equation for `it': it = isOrdered < [1, 2, 3]
What am I missing here?
Since < is infix, you have to wrap it in parens. This converts it to be prefixed.
1 < 2 ==> (<) 1 2
1 + 5 ==> (+) 1 5
Then you're code becomes
isOrdered (<) [1, 2, 3]
This is actually part of a more general concept of sectioning. You can completely convert an infix operator to prefix with parens, or partially apply it like this
\x -> x + 1 ===> (+1)
\x -> 2 ^ x ===> (2^)
The only place where this goes a bit pear-shaped is with -. Since - is a super special prefix operator defined by the Haskell language, you can't do (-2), since it's not clear whether this is a section or a number. Haskell chooses a number, but if you want a section, there is a function subtract.
\x -> x - 2 ==> subtract 2
This works:
isOrdered (<) [1,2,3]
Not sure why, though. It’s a general thing:
Prelude> :type <
<interactive>:1:1: parse error on input `<'
Prelude> :type (<)
(<) :: Ord a => a -> a -> Bool
I’m sure others will explain.
When passing an operator to a higher level function, you have to surround it with parentheses:
isOrdered (<) [1, 2, 3]
You also have to do this for partially applied operators
map (== 2) [1, 2, 3]
This is not an answer to your question, but just a stylistic tip: idiomatic Haskell code should use pattern matching instead of head/tail. Pattern matching statically ensures that you don't accidentally try to access inexistent elements.
The way you would write your function using pattern matching is:
isOrdered :: (a -> a -> Bool) -> [a] -> Maybe Bool
isOrdered mark (x:y:_) = Just (x `mark` y)
isOrdered _ _ = Nothing
Note that I've included a case for when the list does not contain two elements and wrapped the result in a Maybe. This prevents run-time errors by forcing you to handle that case.