
Hi, Alejandro Gomez already posted an answer that should be enough for you to figure out the solution by yourself, but I decided to post mine anyway, in case you have trouble understanding how to proceed. On Sat, Feb 15, 2014 at 01:42:15PM -0600, James Toll wrote:
Prelude> let lower x = filter (\y -> mod x y == 0) [2..(ceiling . sqrt) x] Prelude> lower 36
<interactive>:6:1: No instance for (RealFrac b0) arising from a use of `lower' The type variable `b0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance RealFrac Double -- Defined in `GHC.Float' instance RealFrac Float -- Defined in `GHC.Float' instance Integral a => RealFrac (GHC.Real.Ratio a) -- Defined in `GHC.Real' In the expression: lower 36 In an equation for `it': it = lower 36
<interactive>:6:7: No instance for (Num b0) arising from the literal `36' The type variable `b0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Num Double -- Defined in `GHC.Float' instance Num Float -- Defined in `GHC.Float' instance Integral a => Num (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus three others In the first argument of `lower', namely `36' In the expression: lower 36 In an equation for `it': it = lower 36
At this point, I’m not sure what I need to do to get his working properly. It appears to be a type error, but I’m apparently not understanding the error message enough to fix the problem. Any suggestions would be appreciated.
Your first instinct should be to look at the type signature of the function you just wrote, so you can figure out what `b0` means: λ: :t lower lower :: (Floating b, Integral b, RealFrac b) => b -> [b] See? It expects to be given something that belongs to Floating, Integral and RealFrac typeclasses. The Haskell Report contains a nice image of the dependencies between typeclasses along with the actual types that instantiate them[1] From looking at it, you can deduce that there is no type that belongs to all three typeclasses. Thus the type error. 1. https://www.haskell.org/onlinereport/classes.gif To fix this, let's take a step back and deconstruct your function to see where each of the constraints (the thing in the parentheses that goes before the type) comes from. It all starts with `sqrt`, which has the following type: λ: :t sqrt sqrt :: Floating a => a -> a By looking at the aforementioned diagram again, you can conclude that `a` here is either Float or Double. Next, you compose `sqrt` with `ceiling`, which has the following type: λ: :t ceiling ceiling :: (Integral b, RealFrac a) => a -> b Here, `a` can be Float or Double, and `b` is either Int or Integer. After the composition you have a function with the following type: λ: :t (ceiling . sqrt) (ceiling . sqrt) :: (Floating b, Integral c, RealFrac b) => b -> c It accepts Float or Double (which both belong to Floating and RealFrac typeclasses) and returns Int or Integer. But you want to feed it an Int! Unlike many other languages, Haskell never casts (converts) types unless you order to do so. So you need some function to convert an instance of Integral typeclass (Int or Integer) into instance of both Floating and RealFrac, i.e. a function with the following type: (Integral a, Floating b, RealFrac b) => a -> b For that, we have Hoogle[2] Type in the signature, hit Search and you will be presented with a list of matching functions. `fromIntegral`, which is the second result I've been given, is *exactly* what you need. Let's use it, rewriting `lower` as λ: let lower x = filter (\y -> mod x y == 0) [2..(ceiling . sqrt) (fromIntegral x)] λ: :t lower lower :: Integral a => a -> [a] 2. https://www.haskell.org/hoogle/ As you can see, you've got a function that accepts any instance of Integral typeclass, i.e. Int and Integer types. Precisely what was required. Hope that makes sense. -- Regards, Alexander Batischev