
You can also do something like this (assuming -fglasgow-exts or
LANGUAGE Rank2Types):
f :: forall b. Fractional b => (forall a. Num a => a) -> b
f x = (1/x)^x
This says that the argument to f has to be able to be instantiated at
any numeric type, such as the result of a call to "fromInteger". Now,
the compiler is free to instantiate the first x at Double and the
second at Integer. Here's what it looks like in GHCi:
GHCi, version 6.8.2: http://www.haskell.org/ghc/ :? for help
Loading package base ... linking ... done.
Prelude> :set -XRank2Types -XPatternSignatures
Prelude> let f (x :: forall a. Num a => a) = (1 / x)^x
Prelude> :t f
f :: (Fractional t) => (forall a. (Num a) => a) -> t
Prelude> f 3
3.7037037037037035e-2
Higher rank types don't have inference, so you need to annotate your
function for them to work.
-- ryan
On 2/25/08, Ben
On Feb 25, 2008, at 4:11 PM, Philippa Cowderoy wrote: On Mon, 25 Feb 2008, Ben wrote:
<interactive>:1:8: Ambiguous type variable `t' in the constraints: `Fractional t' arising from a use of `/' at <interactive>:1:8-10 `Integral t' arising from a use of `^' at <interactive>:1:7-15 Probable fix: add a type signature that fixes these type variable(s)
/ doesn't do integer division, so from there it concludes that you're working with a Fractional type - Haskell never coerces behind your back, so not only the result of / but also its parameters are Fractional.
^ only works for Integral types. You might consider that a little arbitrary, but hey - it's mostly like that because it's much easier to raise something to an integer power.
There's no default it can pick that's both Fractional and Integral, so it doesn't know what type the expression should have and it's asking you to tell it ("add a type signature that fixes these type variable(s)"). In practice you won't be able to unless you've got a broken number type handy, but that's the way things go.
Ok, that makes sense. There's no num k that's both Fractional and Integral, where as in the case where I had the number literals, those were two different instances. What's the usual way of working around this? Something like
(\k -> (1/ fromInteger k) ^ k) 3
? _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe