Why is `fmap` needed to call `succ` on a `Maybe Integer`? - haskell

I am brand new to Haskell and am working on a practice Collatz conjecture problem. The required output is the number of steps needed to get to 1 from a given integer. This is the first time I've had to use the Maybe type, which may be contributing to my confusion.
I have this working solution based on another solution I found to the same problem:
collatz :: Integer -> Maybe Integer
collatz n
| n <= 0 = Nothing
| n == 1 = Just 0
| even n = fmap succ . collatz $ n `div` 2
| otherwise = fmap succ . collatz $ 3 * n + 1
What is unclear to me is why it is necessary to use fmap succ in this situation. Based on my current understanding, I would expect to just be able to call succ on the output of the recursive call to collatz in order to increment it; however, this throws an error:
> No instance for (Enum (Maybe Integer))
arising from a use of `succ'
It looks like the error has something to do with calling succ on a Maybe Integer type instead of an Integer. Is the error because a Maybe Integer isn't considered enumerable in Haskell? If so why does calling fmap succ solve this problem?

If you just start learning Haskell, using . and $ needlessly present an additional cognitive load for you. What you have is simpler written as
collatz :: Integer -> Maybe Integer
collatz n
| n <= 0 = Nothing
| n == 1 = Just 0
| even n = fmap succ (collatz (n `div` 2))
| otherwise = fmap succ (collatz (3 * n + 1))
Now, what is succ? If we look at its type,
> :t succ
succ :: Enum a => a -> a
the main thing to notice is that the input and the output types are one and the same. It is also an instance of the Enum class of types, which is just to say that this type implements its specific version of the succ function (it's a bit circular that way).
Since we're dealing with Integers, which do implement their version of succ as
succ :: Integer -> Integer
succ i = i + 1
it's all good and taken care of.
Except collatz :: Integer -> Maybe Integer takes an Integer and returns a Maybe Integer:
-- pseudocode
Maybe Integer = Nothing
| Just Integer
-- ^ tags ^ types of contained data
So we need to apply succ to the contained Integer. And that's the job of fmap:
-- pseudocode
> :t fmap
fmap :: Functor f => (a -> b) -> f a -> f b
> :t fmap # Maybe
fmap :: (a -> b) -> Maybe a -> Maybe b
> :t fmap # Maybe succ # Integer
fmap :: Maybe Integer -> Maybe Integer
Which is a generic function defined by a class of types that each define their specialized version of it. As Maybe indeed does:
-- pseudocode:
fmap f Nothing = Nothing
fmap f (Just i) = Just (f i)
-- ^^ f applied on the "inside"
-- ^^ when there is something in there

Related

Struggling with Haskell type system

I am trying to learn some Haskell by doing basic tasks in the particular case I am trying to implement some basic function for primality check, but I really can figure out the types, my code is
isPrime :: (Num a) => a -> Bool
isPrime n
| n <= 1 = False
| otherwise = not $ 0 `elem` map (mod n) [2..m] where m = floor $ sqrt n
I tried instead of (Num a) => a to use different number types or to use sqrt with fromIntegral but I still get error messages, like:
*Could not deduce (Floating a) arising from a use of `sqrt'
from the context: Num a
bound by the type signature for:
isPrime :: forall a. Num a => a -> Bool
at Helpers.hs:5:1-31
Possible fix:
add (Floating a) to the context of
the type signature for:
isPrime :: forall a. Num a => a -> Bool
* In the second argument of `($)', namely `sqrt n'
In the expression: floor $ sqrt n
In an equation for `m': m = floor $ sqrt n
| otherwise = not $ 0 `elem` map (mod n) [2..m] where m = floor $ sqrt n
I can really use some help here, thank you in advance.
As others have mentioned, the use of mod requires a to be Integral, and the use of sqrt requires a to be Floating. Judging by the name of your function, I'm assuming that you want to use it on integral types.
So, you can fix this by changing your signature to isPrime :: (Integral a) => a -> Bool, then precomposing sqrt with fromIntegral. You could do something like
where m = floor . sqrt . fromIntegral $ n
Another option would be to replace [1..m] with something like takeWhile (\x -> x * x <= n) [1..] to avoid the need for Floating.
You have two problems in your code:
Incompatible types.
Calling both sqrt n and (mod n) reqiure n to be both Floating and Integral at the same time.
Insufficient context. Requiring only (Num a) does not allow neither of the operations.
A possible fix would be: a) narrow down type context to a much more concise (Integral a); b) add fromIntegral to sqrt's argument:
isPrime :: Integral a => a -> Bool
isPrime n
| n <= 1 = False
| otherwise = not $ 0 `elem` map (mod n) [2..m] where m = floor $ sqrt $fromIntegral n
The issue the compiler is describing is that you're applying incompatible operations to the same type: mod requires Integral a, sqrt requires Floating a, and no type satisfies both. You could work around that using type conversions like fromIntegral and ceiling, but you'd want to be careful to avoid rounding errors. For my test, I removed the type constraint and used m = ceiling $ sqrt $ fromIntegral n, which led to the inferred type isPrimeSqrt :: Integral a => a -> Bool.
Another approach is to consider why the conflict was hit and look for other solutions. The reason for sqrt is to produce an optimized stopping point for the test. Can we find that stopping point in another manner?
As it turns out, while division is expensive, it frequently produces two results: the quotient and remainder. With mod you're looking for the latter, but we have divMod and quotRem which produce both. So it could be worth testing if that's notably slower than the plain mod test (benchmark results, comparing [2..] vs [2..m]).
isPrime n = (n > 1) && null (filter isFactor (takeWhile notTooHigh divisors))
where notTooHigh (divisor,quotient,_) = divisor <= quotient
isFactor (_,_,remainder) = remainder == 0
divisors = [(divisor,quotient,remainder) |
divisor <- 2:[3,5..],
let (quotient,remainder) = quotRem n divisor]

how does Haskell know `xs` is a list in the function definition?

In book.realworldhaskell.org, types and functions part under Conditional evaluation section, it is given the following example:
-- file: ch02/myDrop.hs
myDrop n xs = if n <= 0 || null xs
then xs
else myDrop (n - 1) (tail xs)
I did understand the implementation of the function, but my question is that how does Haskell know xs is a list ?
Type inference
You write:
myDrop n xs = if n <= 0 || null xs
then xs
else myDrop (n - 1) (tail xs)
So Haskell first assumes that the function has type myDrop :: a -> (b -> c) (it first does not make any assumptions regarding the types). So in memory we store:
myDrop :: a -> b -> c
n :: a
xs :: b
But now it will start deriving types.
We see for instance n <= 0. Now the function (<=) has signature (<=) :: Ord d => d -> d -> Bool. So that means that 0 :: d, and we now that for number literals, it holds that 0 :: Num e => e. So we can add Num a to the type constraint.
We also see null xs, null has signature null :: [f] -> Bool, so that means that a ~ [f] (here ~ means type equality). We also have to check that the expression n <= 0 || null xs results in a Bool (since it is the condition of the if-then-else. Since (||) has as type (||) :: Bool -> Bool -> Bool, it means that n <= 0 and null xs should return Bools. This holds: since (<=) has type Ord d -> d -> Bool, and null :: [f] -> Bool. So after type inference of the first line, we have:
myDrop :: (Num a, Ord a) => a -> [f] -> c
n :: (Num a, Ord a) => a
xs :: [f]
Now we still need to typecheck the second and third line. In an if-then-else clause, the then expression, and else expression need to have the same type, so we now that the type of xs is the same as myDrop (n-1) (tail xs). So even without knowing the signature of myDrop (n-1) (tail xs) we know already that it needs to have type myDrop :: g -> h -> [f] (here we currently do not know the type of g and h.
Since we are deriving the type of myDrop, we can check the type we have constructed thus far, with the one we are calling, so we compare it like:
myDrop :: (Num a, Ord a) => a -> [f] -> c -- currently derived
myDrop :: g -> h -> [f] -- called
So we derive that: a ~ g, and c ~ h ~ [f]. So now we know that myDrop has type:
myDrop :: (Num a, Ord a) => a -> [f] -> [f]
We now still need to typecheck the arguments. We see for instance that the first argument in the call is n - 1, the signature of (-) is (-) :: Num i => i -> i -> i, and 1 is a number literal, so 1 :: Num j => j, so we derive that in this specific context i ~ j ~ a, and as a result n - 1 :: a, thus holds with the derived type for the function.
We also know that tail has signature tail :: [k] -> [k]. Since we call it with xs :: [f], we know that f ~ k, and thus tail xs :: [f], this again holds. We did not had to derive a or f, further, so we can set the type as:
myDrop n xs :: (Num a, Ord a) => a -> [f] -> [f]
Improving the function
The above function works, and it will work regardless what input we provide. But I would call it a bit "unsafe" in the sense that it works because we work with contracts the function we call (tail and null). For example tail will error in case we provide it an empty list. Yes, this can never happen, since null checks this. But we thus have to reason about that ourselves. It is usually better to work only with total functions: functions that always return valid output.
We can here perform pattern matching in the head of the function. A Haskell compiler can derive that we are missing patterns, so if we turn on that feature, then we can validate that all the cases are covered.
We can write it as:
myDrop :: (Num a, Ord a) => a -> [f] -> [f]
myDrop _ [] = []
myDrop n xa#(_:xs) | n <= 0 = xa
| otherwise = myDrop (n-1) xs
So here the first line convers the case where the list is empty (regardless what n is, we return an empty list). In case the list is not empty, it has as pattern (_:xs) (and we also keep a reference to xa, the entire list. In case n <= 0, we return xa, otherwise we decrement n, and make a recursive call on the tail.
You are calling null and tail on xs.
null :: [a] -> Bool
tail :: [a] -> [a]
The arguments to both are lists, so Haskell can infer that, if you are calling null xs or tail xs, the type of xs must be [a].
It doesn't. Haskell doesn't know that xs is a list until it tries to compile the invocation.
When you call myDrop 3 someList Haskell knows that null someList can accept someList, and that tail someList can be called on someList and returns a list. Haskell's (magical) type system can infer (at compile time) how to compile myDrop n xs with what it already knows.
In theory, if you made some "not-list" things that worked for tail and null you could call myDrop 3 notList and get sensible results.

GHC not deducing the way I would like it to :-(

chainQuery :: (Enum a, Integral a, Ord b) => a -> b -> [c]
chainQuery n min = map length $ filter beatingLength $ map chain [1..n]
where
beatingLength :: [a] -> Bool
beatingLength xs = length xs > min
chain :: (Integral a) => a -> [a]
chain n
| n <= 1 = [n]
| even n = n:(chain $ div n 2)
| otherwise = n:(chain $ n * 3 + 1)
In the code sample above why isn't GHC able to deduce that 'c' is an Int by looking at the type definition for length?
Why does GHC need to know anything about 'b' other than that it is an Ord?
Is there a better way to write this function?
GHC is able to infer [Int] as the result type for the function. The problem is that you've claimed in your type signature that it should be more polymorphic, that the result could be a list of any type, which does not make sense since the return value comes from the map length so it must have type [Int]. This is what GHC is complaining about when it says Could not deduce (c ~ Int).
You're comparing min to length xs. The greater-than operator has the type (>) :: (Ord a) => a -> a -> Bool, which means that both sides must be the same type. The type of length xs is Int, so this forces min to be Int as well.
Probably. For example, you can map the length before doing the filtering. This makes it easy to use an operator section instead of your beatingLength function. You can also move the parenthesis to save a use of $ to make the code a bit neater.
chainQuery n min = filter (> min) $ map (length . chain) [1..n]
where chain n | n <= 1 = [1]
| even n = n : chain (n `div` 2)
| otherwise = n : chain (3*n + 1)
For reference, the easiest way to solve a problem like this is to remove your type signature and see what type was inferred in GHCi using the :t command. In this case, the inferred type is
*Main> :t chainQuery
chainQuery :: Integral a => a -> Int -> [Int]

Transforming a function that computes a fixed point

I have a function which computes a fixed point in terms of iterate:
equivalenceClosure :: (Ord a) => Relation a -> Relation a
equivalenceClosure = fst . List.head -- "guaranteed" to exist
. List.dropWhile (uncurry (/=)) -- removes pairs that are not equal
. U.List.pairwise (,) -- applies (,) to adjacent list elements
. iterate ( reflexivity
. symmetry
. transitivity
)
Notice that we can abstract from this to:
findFixedPoint :: (a -> a) -> a -> a
findFixedPoint f = fst . List.head
. List.dropWhile (uncurry (/=)) -- dropWhile we have not reached the fixed point
. U.List.pairwise (,) -- applies (,) to adjacent list elements
. iterate
$ f
Can this function be written in terms of fix? It seems like there should be a transformation from this scheme to something with fix in it, but I don't see it.
There's quite a bit going on here, from the mechanics of lazy evaluation, to the definition of a fixed point to the method of finding a fixed point. In short, I believe you may be incorrectly interchanging the fixed point of function application in the lambda calculus with your needs.
It may be helpful to note that your implementation of finding the fixed-point (utilizing iterate) requires a starting value for the sequence of function application. Contrast this to the fix function, which requires no such starting value (As a heads up, the types give this away already: findFixedPoint is of type (a -> a) -> a -> a, whereas fix has type (a -> a) -> a). This is inherently because the two functions do subtly different things.
Let's dig into this a little deeper. First, I should say that you may need to give a little bit more information (your implementation of pairwise, for example), but with a naive first-try, and my (possibly flawed) implementation of what I believe you want out of pairwise, your findFixedPoint function is equivalent in result to fix, for a certain class of functions only
Let's take a look at some code:
{-# LANGUAGE RankNTypes #-}
import Control.Monad.Fix
import qualified Data.List as List
findFixedPoint :: forall a. Eq a => (a -> a) -> a -> a
findFixedPoint f = fst . List.head
. List.dropWhile (uncurry (/=)) -- dropWhile we have not reached the fixed point
. pairwise (,) -- applies (,) to adjacent list elements
. iterate f
pairwise :: (a -> a -> b) -> [a] -> [b]
pairwise f [] = []
pairwise f (x:[]) = []
pairwise f (x:(xs:xss)) = f x xs:pairwise f xss
contrast this to the definition of fix:
fix :: (a -> a) -> a
fix f = let x = f x in x
and you'll notice that we're finding a very different kind of fixed-point (i.e. we abuse lazy evaluation to generate a fixed point for function application in the mathematical sense, where we only stop evaluation iff* the resulting function, applied to itself, evaluates to the same function).
For illustration, let's define a few functions:
lambdaA = const 3
lambdaB = (*)3
and let's see the difference between fix and findFixedPoint:
*Main> fix lambdaA -- evaluates to const 3 (const 3) = const 3
-- fixed point after one iteration
3
*Main> findFixedPoint lambdaA 0 -- evaluates to [const 3 0, const 3 (const 3 0), ... thunks]
-- followed by grabbing the head.
3
*Main> fix lambdaB -- does not stop evaluating
^CInterrupted.
*Main> findFixedPoint lambdaB 0 -- evaluates to [0, 0, ...thunks]
-- followed by grabbing the head
0
now if we can't specify the starting value, what is fix used for? It turns out that by adding fix to the lambda calculus, we gain the ability to specify the evaluation of recursive functions. Consider fact' = \rec n -> if n == 0 then 1 else n * rec (n-1), we can compute the fixed point of fact' as:
*Main> (fix fact') 5
120
where in evaluating (fix fact') repeatedly applies fact' itself until we reach the same function, which we then call with the value 5. We can see this in:
fix fact'
= fact' (fix fact')
= (\rec n -> if n == 0 then 1 else n * rec (n-1)) (fix fact')
= \n -> if n == 0 then 1 else n * fix fact' (n-1)
= \n -> if n == 0 then 1 else n * fact' (fix fact') (n-1)
= \n -> if n == 0 then 1
else n * (\rec n' -> if n' == 0 then 1 else n' * rec (n'-1)) (fix fact') (n-1)
= \n -> if n == 0 then 1
else n * (if n-1 == 0 then 1 else (n-1) * fix fact' (n-2))
= \n -> if n == 0 then 1
else n * (if n-1 == 0 then 1
else (n-1) * (if n-2 == 0 then 1
else (n-2) * fix fact' (n-3)))
= ...
So what does all this mean? depending on the function you're dealing with, you won't necessarily be able to use fix to compute the kind of fixed point you want. This is, to my knowledge, dependent on the function(s) in question. Not all functions have the kind of fixed point computed by fix!
*I've avoided talking about domain theory, as I believe it would only confuse an already subtle topic. If you're curious, fix finds a certain kind of fixed point, namely the least available fixed point of the poset the function is specified over.
Just for the record, it is possible to define the function findFixedPoint using fix.
As Raeez has pointed out, recursive functions can be defined in terms of fix.
The function that you are interested in can be recursively defined as:
findFixedPoint :: Eq a => (a -> a) -> a -> a
findFixedPoint f x =
case (f x) == x of
True -> x
False -> findFixedPoint f (f x)
This means that we can define it as fix ffp where ffp is:
ffp :: Eq a => ((a -> a) -> a -> a) -> (a -> a) -> a -> a
ffp g f x =
case (f x) == x of
True -> x
False -> g f (f x)
For a concrete example, let us assume that f is defined as
f = drop 1
It is easy to see that for every finite list l we have findFixedPoint f l == [].
Here is how fix ffp would work when the "value argument" is []:
(fix ffp) f []
= { definition of fix }
ffp (fix ffp) f []
= { f [] = [] and definition of ffp }
[]
On the other hand, if the "value argument" is [42], we would have:
fix ffp f [42]
= { definition of fix }
ffp (fix ffp) f [42]
= { f [42] =/= [42] and definition of ffp }
(fix ffp) f (f [42])
= { f [42] = [] }
(fix ffp) f []
= { see above }
[]

type constructor or class error

dreiNplusEins :: Integer -> [Integer]
dreiNplusEins n = if n == 1 then [1] else if n `mod` 2 == 0 then
[n] ++ dreiNplusEins (n `div` 2)
else
[n] ++ dreiNplusEins (n * 3 + 1)
maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze,ObereGrenze,MaxZyklaenge)
maxZyklus m n = if m > n then (m,n,0) else if m == n then
(m,n,length(dreiNplusEins m))
else
(m,n,0)
type UntereGrenze = Integer
type ObereGrenze = Integer
type MaxZykLaenge = Integer
this is my program and this gives error as Not in scope: type constructor or class `MaxZyklaenge' how can i fix it ?
You have a typo in the type name:
In the type signature of maxZyklus you write MaxZyklaenge (lower case l), but in the type definition you write MayZykLaenge (capital L).
Even if you fix the typo you'll still get an error, since length returns an Int where you need an Integer. The following is one way to fix this (I've also rewritten your code to use guards):
import Data.List (genericLength)
dreiNplusEins :: Integer -> [Integer]
dreiNplusEins 1 = [1]
dreiNplusEins n
| n `mod` 2 == 0 = n : dreiNplusEins (n `div` 2)
| otherwise = n : dreiNplusEins (n * 3 + 1)
maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze, ObereGrenze, MaxZyklaenge)
maxZyklus m n
| m == n = (m, n, genericLength $ dreiNplusEins m)
| otherwise = (m, n, 0)
type UntereGrenze = Integer
type ObereGrenze = Integer
type MaxZyklaenge = Integer
You could also use fromIntegral . length if you don't want the extra import, but I personally think genericLength is a little clearer.
Also, if you're interested, here's an arguably nicer way to write the first function:
dreiNplusEins :: Integer -> [Integer]
dreiNplusEins = (++[1]) . takeWhile (/=1) . iterate f
where
f n | even n = n `div` 2
| otherwise = n * 3 + 1
This just says "iteratively apply f until you hit a 1, and then tack a 1 on the end".
To find the number in a given range that produces the longest chain, you can use the following function:
longestBetween :: (Enum a, Integral b) => (a -> [b]) -> (a, a) -> (a, b)
longestBetween f (m, n)
= maximumBy (comparing snd)
. zip [m..n] $ map (genericLength . f) [m..n]
The first argument is the function that creates the list and the second is the range. The return value is a tuple containing the desired number in the range and the length of its list. Note that we need these additional imports:
import Data.List (genericLength, maximumBy)
import Data.Ord (comparing)
We can test as follows:
*Main> longestBetween dreiNplusEins (100, 1000)
(871,179)
Implementing the maxZyklus function you specify in the comments just takes a couple of minor changes at this point:
maxZyklus m n = (m, n, maximum $ map (genericLength . dreiNplusEins) [m..n])
maxZyklus 11 22 gives the desired (11, 22, 21).
Haskell is case sensitive.
In the type signature of maxZyklus:
... ,MaxZyklaenge)
-- # ^
But you have:
type MaxZykLaenge = Integer
-- # ^
It's defined as MaxZykLaenge (note the "L"), whereas you wrote the type as "MaxZyklaenge". Haskell is case-sensitive.

Resources