I got the idea of defining an operator that takes a (possibly) multidimensional list, and a list of indices, and returns the element. My proto attempt was:
(!!!) xs [i] = xs !! i
(!!!) xs (cI : restI) = (xs !! cI) !!! restI
In retrospect, this obviously has a lot of problems. I couldn't figure out a type signature first off, then I realized that in line 2, the return type of (xs !! cI) will constantly change, and may not always even be a list (on the last "iteration")
I realized that to access a multi-dimensional array using the standard subscript operator, you can simply chain it like:
[[1,2,3],[4,5,6],[7,8,9]] !! 1 !! 1 = 5
And realized that that looks a lot like a fold, so I tried:
(!!!) xxs inds = foldl (!!) xxs inds
or simply (!!!) = foldl (!!)
But I get the same error as my first attempt; that I'm trying to construct an infinite type.
Is this type of function even possible (through a hack or otherwise)? I'm starting to think that its type is just too up in the air to work.
Just as an example, I was aiming for the following:
[[1,2,3],[4,5,6],[7,8,9]] !!! [1,1] = 5
As long as you are not bound to using a list to store your indices, you can do this without much effort. The indices must be passed as a datatype which encodes how many indices there are in the type. The canonical length indexed list type looks something like this:
data Nat = Z | S Nat
infixr 5 :>
data Vector (n :: Nat) a where
Nil :: Vector Z a
(:>) :: a -> Vector n a -> Vector (S n) a
Then your function is
(!!!) a Nil = a
(!!!) a (i :> is) = (a !! i) !!! is
You'll notice this doesn't compile. This is because the types of a in the first and second lines are different. The type of a must depend on the type of the indices, and you must tell the compiler exactly how they depend on it. The dependence is quite straightforward; when there are n indices, there must be a list of n dimensions:
type family Dimension (n :: Nat) (v :: * -> *) (x :: *) :: * where
Dimension Z v x = x
Dimension (S n) v x = v (Dimension n v x)
Then the type of the above is quite simply
(!!!) :: Dimension n [] a -> Vector n Int -> a
I don't know how familiar you are with the more advanced features of the Haskell type system, but the above requires type families and data kinds.
Related
I want to shift a list by n elements to the left. Why do I get an error if I want to change the order from (x:xs) to (xs:x)?
shift n list#(x:xs)
| n == 0 = list
| otherwise = shift (n-1) (xs:x) -- (xs:x) error
Occurs check: cannot construct the infinite type: a ~ [a]
I don't know how to interpret this error. Maybe someone of you can help me.
Thank you very much.
EDIT: As it was already mentioned, the correct term to use is rotate and not shift
Why do I get an error if I want to change the order from (x:xs) to (xs:x)?
Because the types do not match. The type of (:) is (:) :: a -> [a] -> [a]. It thus expects an element x (type a) and a list with the rest of the elements (type [a]). You can not just use (:) in the opposite way.
You can use the (++) :: [a] -> [a] -> [a] to concatenate two lists together. We can thus rotate to the left by dropping n elements from the list and concatenating this with the first n elements of the list to this.
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = drop n list ++ take n list
or we can, like #YannVernier says, use splitAt :: Int -> [a] -> ([a], [a]):
rotateL :: Int -> [a] -> [a]
rotateL 0 list = list
rotateL n list | n < 0 = error "Negative index"
| otherwise = lb ++ la
where (la, lb) = splitAt n list
or without mentioning the list parameter:
rotateL :: Int -> [a] -> [a]
rotateL 0 = id
rotateL n | n < 0 = error "Negative index"
| otherwise= uncurry (flip (++)) . splitAt n
Note: based on how your attempt, I think you actually want to rotate the list to the left, not shift it, since that would mean that you simply drop the first n elements, and fill it perhaps with some extra value.
Note: in case n is larger than the length of the list, then the rotateL will act as an identity function. That might not be the desired behavior. I leave it as an exercise to fix this edge-case.
It's not the names that define the types, but the positions in a function call, or type declarations. If we check the type of :, we see that the second argument is a list:
Prelude> :t (:)
(:) :: a -> [a] -> [a]
So pattern matching on this constructor will always give you the head and tail, not the init and last. Thus, using both x:xs and xs:x, you've declared that a and [a] are the same type, and the compiler balks. You could perform the append using e.g. xs ++ [x].
Data.Sequence has a type that does support both head and last patterns in the operators :<| and |>:.
In general, (singly linked) lists only make the head element efficiently accessible; operations like appending or even checking lengths are costly. When all you need is a stream or stack, they're great, but a long distance reordering operation like the rotation is better handled by a rope or circular buffer type. Either is available in Haskell, in e.g. container's Seq or ring-buffer's RingBuffer. Data.ByteString.Lazy and Data.Text.Lazy are also rope types.
I am writing a small function in Haskell to check if a list is a palindrome by comparing it with it's reverse.
checkPalindrome :: [Eq a] -> Bool
checkPalindrome l = (l == reverse l)
where
reverse :: [a] -> [a]
reverse xs
| null xs = []
| otherwise = (last xs) : reverse newxs
where
before = (length xs) - 1
newxs = take before xs
I understand that I should use [Eq a] in the function definition because I use the equality operator later on, but I get this error when I compile:
Expected kind ‘*’, but ‘Eq a’ has kind ‘GHC.Prim.Constraint’
In the type signature for ‘checkPalindrome’:
checkPalindrome :: [Eq a] -> Bool
P.s Feel free to correct me if I am doing something wrong with my indentation, I'm very new to the language.
Unless Haskell adopted a new syntax, your type signature should be:
checkPalindrome :: Eq a => [a] -> Bool
Declare the constraint on the left hand side of a fat-arrow, then use it on the right hand side.
Unlike OO languages, Haskell makes a quite fundamental distinction between
Constraints – typeclasses like Eq.
Types – concrete types like Bool or lists of some type.
In OO languages, both of these would be represented by classes†, but a Haskell type class is completely different. You never have “values of class C”, only “types of class C”. (These concrete types may then contain values, but the classes don't.)
This distinction may seem pedantic, but it's actually very useful. What you wrote, [Eq a] -> Bool, would supposedly mean: each element of the list must be comparable... but comparable to what? You could have elements of different type in the list, how do you know that these elements are comparable to each other? In Haskell, that's no issue, because whenever the function is used you first settle on one type a. This type must be in the Eq class. The list then must have all elements from the same type a. This way you ensure that each element of the list is comparable to all of the others, not just, like, comparable to itself. Hence the signature
checkPalindrome :: Eq a => [a] -> Bool
This is the usual distinction on the syntax level: constraints must always‡ be written on the left of an => (implication arrow).
The constraints before the => are “implicit arguments”: you don't explicitly “pass Eq a to the function” when you call it, instead you just pass the stuff after the =>, i.e. in your example a list of some concrete type. The compiler will then look at the type and automatically look up its Eq typeclass instance (or raise a compile-time error if the type does not have such an instance). Hence,
GHCi, version 7.10.2: http://www.haskell.org/ghc/ :? for help
Prelude> let palin :: Eq a => [a] -> Bool; palin l = l==reverse l
Prelude> palin [1,2,3,2,1]
True
Prelude> palin [1,2,3,4,5]
False
Prelude> palin [sin, cos, tan]
<interactive>:5:1:
No instance for (Eq (a0 -> a0))
(maybe you haven't applied enough arguments to a function?)
arising from a use of ‘palin’
In the expression: palin [sin, cos, tan]
In an equation for ‘it’: it = palin [sin, cos, tan]
...because functions can't be equality-compared.
†Constraints may in OO also be interfaces / abstract base classes, which aren't “quite proper classes” but are still in many ways treated the same way as OO value-classes. Most modern OO languages now also support Haskell-style parametric polymorphism in addition to “element-wise”/covariant/existential polymorphism, but they require somewhat awkward extends trait-mechanisms because this was only implemented as an afterthought.
‡There are also functions which have “constraints in the arguments”, but that's a more advanced concept called rank-n polymorphism.
This is really an extended comment. Aside from your little type error, your function has another problem: it's extremely inefficient. The main problem is your definition of reverse.
reverse :: [a] -> [a]
reverse xs
| null xs = []
| otherwise = (last xs) : reverse newxs
where
before = (length xs) - 1
newxs = take before xs
last is O(n), where n is the length of the list. length is also O(n), where n is the length of the list. And take is O(k), where k is the length of the result. So your reverse will end up taking O(n^2) time. One fix is to just use the standard reverse function instead of writing your own. Another is to build up the result recursively, accumulating the result as you go:
reverse :: [a] -> [a]
reverse xs0 = go [] xs0
go acc [] = acc
go acc (x : xs) = go (x : acc) xs
This version is O(n).
There's another source of inefficiency in your implementation:
checkPalindrome l = (l == reverse l)
This isn't nearly as bad, but let's look at what it does. Suppose we have the string "abcdefedcba". Then we test whether "abcdefedcba" == "abcdefedcba". By the time we've checked half the list, we already know the answer. So we'd like to stop there! There are several ways to accomplish this. The simplest efficient one is probably to calculate the length of the list as part of the process of reversing it so we know how much we'll need to check:
reverseCount :: [a] -> (Int, [a])
reverseCount xs0 = go 0 [] xs0 where
go len acc [] = (len, acc)
go len acc (x : xs) = len `seq`
go (len + 1) (x : acc) xs
Don't worry about the len `seq` bit too much; that's just a bit of defensive programming to make sure laziness doesn't make things inefficient; it's probably not even necessary if optimizations are enabled. Now you can write a version of == that only looks at the first n elements of the lists:
eqTo :: Eq a => Int -> [a] -> [a] -> Bool
eqTo 0 _ _ = True
eqTo _ [] [] = True
eqTo n (x : xs) (y : ys) =
x == y && eqTo (n - 1) xs ys
eqTo _ _ _ = False
So now
isPalindrome xs = eqTo ((len + 1) `quot` 2) xs rev_xs
where
(len, rev_xs) = reverseCount xs
Here's another way, that's more efficient and arguably more elegant, but a bit tricky. We don't actually need to reverse the whole list; we only need to reverse half of it. This saves memory allocation. We can use a tortoise and hare trick:
splitReverse ::
[a] ->
( [a] -- the first half, reversed
, Maybe a -- the middle element
, [a] ) -- the second half, in order
splitReverse xs0 = go [] xs0 xs0 where
go front rear [] = (front, Nothing, rear)
go front (r : rs) [_] = (front, Just r, rs)
go front (r : rs) (_ : _ : xs) =
go (r : front) rs xs
Now
isPalindrome xs = front == rear
where
(front, _, rear) = splitReverse xs
Now for some numbers, using the test case
somePalindrome :: [Int]
somePalindrome = [1..10000] ++ [10000,9999..1]
Your original implementation takes 7.523s (2.316 mutator; 5.204 GC) and allocates 11 gigabytes to build the test list and check if it's a palindrome. My counting implementation takes less than 0.01s and allocates 2.3 megabytes. My tortoise and hare implementation takes less than 0.01s and allocates 1.7 megabytes.
I want to define a simple function in Haskell:
nzp :: [Int] -> (Int,Int,Int)
that accepts a list of integers as input and returns a triple (a,b,c) where a is the amount of numbers in the list less than 0, b is the amount equal to 0 and c is the amount higher than zero. For example,
nzp [3,0,-2,0,4,5] = (1,2,3)
I have to define this function recursively and I can only traverse the list once. How can I do this? I can't seem to grasp the concept of recursively creating a tuple.
Most Regards
Here are some pointers:
To use recursion to build up a value, you need to pass the previous version of the value as an argument, so write
nzp_helper :: [Int] -> (Int,Int,Int) -> (Int, Int, Int)
Decide what the answer is when the list is empty
nzp_helper [] runningTotals = -- what's the answer if the list is empty?
Decide what the answer is when there's something in the list
nzp_helper (i:is) (negatives, positives, zeros) =
| i < 0 = -- write stuff here
| i == 0 = -- I hope you're getting the idea
Kick the whole thing off by defining nzp using nzp_helper.
nzp is = nzp_helper is -- one final argument - what?
Instead of thinking of trying to create a single tuple recursively, you should think about updating an existing tuple containing the counts based on given value. This function would look something like:
update :: (Int, Int, Int) -> Int -> (Int, Int, Int)
update (l,e,g) x | x < 0 = (l+1, e, g)
update (l,e,g) x | x == 0 = (l, e+1, g)
update (l,e,g) x | x > 0 = (l, e, g+1)
Then you can traverse the input list using foldl and accumulate the output tuple:
nzp :: [Int] -> (Int, Int, Int)
nzp = foldl update (0,0,0)
EDIT: As #leftroundabout points out in the comments, you should avoid using foldl since it can lead to space leaks - you can find an explanation in Real World Haskell. You can use the strict version of foldl, foldl' in Data.List
import Data.List
nzp = foldl' update (0,0,0)
I can't seem to grasp the concept of recursively creating a tuple.
I shouldn't think so – in fact, it's impossible! (At least not without GHC extension havoc.)
No, you need to create a tuple in one go. The important thing needed for your function: since you may only traverse the list once, you need to pull through the entire tuple at once as well. As this is apparently homework, I shall instead show how it works with a fold (that is in fact preferrable, but translates quite directly to recursion):
nzp = foldr switchIncr (0,0,0)
where switchIncr x (negatives, zeroes, positives)
| x<0 = (succ negatives, zeroes, positives)
| x==0 = (negatives, succ zeroes, positives)
| otherwise = (negatives, zeroes, succ positives)
New to Haskell too! Perhaps not proper but here is my solution which works.
Define an auxiliary function that accumulates the n,z, and p values
let f (x:xs, (n, z, p)) | x < 0 = f (xs, (n+1, z, p))
| x == 0 = f (xs, (n, z+1, p))
| otherwise = f (xs, (n, z, p+1))
f ([], (n, z, p)) = ([], (n, z, p))
and define nzp in terms of the auxiliary function
let nzp x = snd $ f (x,(0,0,0))
to verify
Prelude> nzp [-1,1,1,-1,0]
(2,1,2)
I am a little over a couple of months into Haskell. A helper/auxilliary function would make running this solution easier.
s3 [] (l,g,z) = (l,g,z)
s3 (x:xs) (l,g,z) = if x<0
then (s3 xs (l+1,g,z))
else if x>0
then (s3 xs (l,g+1,z))
else (s3 xs (l,g,z+1))
This is run with s3 [1,0,-2,3,4,-7,0,-8] (0,0,0) producing
(3,3,2).
Just about any primitive recursive function can be translated into a fold.
I'm trying to implement a type-safe binomial heap. For this, I have two data types whose element types are parametrized by their type-encoded indexes:
data Zero
data Succ a = Succ
{-| A GADT representation of lists with type-encoded length.
Unlike the most common implementation, the type paramater
for values is of kind * -> *. Each element type is
parametrized by its index (counting from the end of the vector),
so the type-encoded numbers decrease from start to end.
-}
data Vec n a where
Nil :: Vec Zero a
Cons :: a n -> Vec n a -> Vec (Succ n) a
{-| A GADT representation of lists whose values are of kind
* -> *. Each element type is parametrized by its by its
index (counting from the start of the vector), so the
type-encoded numbers increase from start to end.
Unlike Vec the type-encode number here doesn't represent
the length, it can be arbitrary (just increasing).
-}
data RVec n a where
RNil :: RVec n a
RCons :: a n -> RVec (Succ n) a -> RVec n a
Vec encodes values with decreasing number parameter, where the last element is always parametrized by Zero. RVec encodes values with increasing number parameter with no other restriction (this is why RNil can produce RVec of any number).
This allows me (for example) to have a list of trees with increasing/decreasing heights, checked by the type system. After implementing a large part of my project, I realized I need a seemingly simple function, which I wasn't able to implement:
vreverse :: Vec n a -> RVec Zero a
It should simply reverse the order of the given list. Any ideas? Thanks in advance.
I believe I found an answer:
vreverse :: Vec n a -> RVec Zero a
vreverse v = f1 v RNil
where
f1 :: Vec n a -> (RVec n a -> RVec Zero a)
f1 Nil = id
f1 (Cons x xs) = f1 xs . RCons x
For your reference, the third article of Issue 16 of the Monad.Reader...which, um, I wrote...discusses type-safe binomial heaps in Haskell, and how to implement them correctly.
I'm trying to write a program in Haskell
that gets a list (of integer) and prints out the number of elements that are bigger than the list's average
So far I tried
getAVG::[Integer]->Double
getAVG x = (fromIntegral (sum x)) / (fromIntegral (length x))
smallerThanAVG:: [Integer]->Integer
smallerThanAVG x = (map (\y -> (if (getAVG x > y) then 1 else 0)) x)
For some reason I'm getting this error
Couldn't match expected type `Double'
against inferred type `Integer'
Expected type: [Double]
Inferred type: [Integer]
In the second argument of `map', namely `x'
It could be that I haven't written the logic correctly, although I think I did..
Ideas?
These errors are the best kind, because they pinpoint where you have made a type error.
So let's do some manual type inference. Let's consider the expression:
map (\y -> (if (getAvg x > y) then 1 else 0)) x
There are a few constraints we know off the bat:
map :: (a -> b) -> [a] -> [b] -- from definition
(>) :: Num a => a -> a -> Bool -- from definition
getAvg :: [Integer] -> Double -- from type declaration
1, 0 :: Num a => a -- that's how Haskell works
x :: [Integer] -- from type declaration of smallerThanAVG
Now let's look at the larger expressions.
expr1 = getAvg x
expr2 = (expr1 > y)
expr3 = (if expr2 then 1 else 0)
expr4 = (\y -> expr3)
expr5 = map expr4 x
Now let's work backwards. expr5 is the same as the RHS of smallerThanAVG, so that means it has the same result type as what you've declared.
expr5 :: Integer -- wrong
However, this doesn't match our other constraint: the result of map must be [b] for some b. Integer is definitely not a list (although if you get facetious, it could be coerced into a list of bits). You probably meant to sum that list up.
expr6 = sum expr5
sum :: Num a => [a] -> a
Now let's work forwards.
expr1 :: Double -- result type of getAvg
y :: Double -- (>) in expr2 requires both inputs to have the same type
expr4 :: (Integer -> [a]) -- because for `map foo xs` (expr5)
-- where xs :: [a], foo must accept input a
y :: Integer -- y must have the input type of expr4
Herein lies the conflict: y cannot be both a Double and an Integer. I could equivalently restate this as: x cannot be both a [Double] and [Integer], which is what the compiler is saying. So tl;dr, the kicker is that (>) doesn't compare different types of Nums. The meme for this sort of problem is: "needs more fromIntegral".
(getAvg x > fromIntegral y)
Your code has two errors.
Although the type signature in the code declares that smallerThanAVG x evaluates to an Integer, its code is map ... x, which clearly evaluates to a list instead of a single Integer.
In the code getAVG x > y, you are comparing a Double to an Integer. In Haskell, you can only compare two values of the same type. Therefore, you have to use fromIntegral (or fromInteger) to convert an Integer to a Double. (This is essentially what caused the error message in the question, but you have to get used to it to figure it out.)
There are several ways to fix item 1 above, and I will not write them (because doing so would take away all the fun). However, if I am not mistaken, the code you are aiming at seems like counting the number of elements that are smaller than the average, in spite of what you write before the code.
Styling tips:
You have many superfluous parentheses in your code. For example, you do not have to parenthesize the condition in an if expression in Haskell (unlike if statement in C or Java). If you want to enjoy Haskell, you should learn Haskell in a good style instead of the Haskell which just works.
You call the variable which represents a list “x” in your code. It is conventional to use a variable name such as xs to represent a list.
Others have explained the errors beautifully.
I'm still learning Haskell but I'd like to provide an alternative version of this function:
greaterThanAvg :: [Int] -> [Int]
greaterThanAvg xs = filter (>avg) xs
where avg = sum xs `div` length xs
cnt = length $ greaterThanAvg [1,2,3,4,5]