# Function that works with both Fractional and Integral

I haven’t been able to figure this out. I see if I remove `mod` which requires `Integral` as I did in `getFnA` it works.

In other languages I know I would do `if (typeof x) == Integral else ...` kind of thing my understanding is you can do a runtime type check in Haskell

The error gives a suggestion “Probable fix: use a type annotation to specify what ‘a0’ should be.” but I have not been able to figure out how to do that.

``````getFn :: (Foldable t, Fractional a, Integral a) => t Char -> Either String (a -> a -> a, String)
getFn str
| '+' `elem` str = Right ((+), "+")
| '-' `elem` str = Right ((-), "-")
| '*' `elem` str = Right ((*), "*")
| '/' `elem` str = Right ((/), "/")
| '%' `elem` str = Right (mod, "%")
| otherwise = Left "Invalid operator. Must be one of +, -, *, /, %"

getFnA :: (Foldable t, Fractional a) => t Char -> Either String (a -> a -> a, String)
getFnA str
| '+' `elem` str = Right ((+), "+")
| '-' `elem` str = Right ((-), "-")
| '*' `elem` str = Right ((*), "*")
| '/' `elem` str = Right ((/), "/")
| otherwise = Left "Invalid operator. Must be one of +, -, *, /, %"

simpleCalc :: IO ()
simpleCalc = do
userInput <- getContents  -- expected: "1+2"
let a = getFn userInput -- Error appears here
...
``````

Here is the error

• Ambiguous type variable ‘a0’ arising from a use of ‘getFn’
prevents the constraint ‘(Fractional a0)’ from being solved.
Relevant bindings include
a :: (a0 → a0 → a0, String)
(bound at /home/klequis/projects/simpleCalc/src/Lib.hs:36:7)
Probable fix: use a type annotation to specify what ‘a0’ should be.
These potential instances exist:
instance Fractional Double – Defined in ‘GHC.Float’
instance Fractional Float – Defined in ‘GHC.Float’
…plus 9 instances involving out-of-scope types
(use -fprint-potential-instances to see them all)
• In the expression: getFn userInput
In an equation for ‘a’: a = getFn userInput
In the expression:
do userInput ← getContents
let a = getFn userInput
print "hi"typecheck(-Wdeferred-type-errors)

1 Like

You can implement that suggestion like this:

``````simpleCalc :: IO ()
simpleCalc = do
userInput <- getContents  -- expected: "1+2"
let
a = getFn userInput -- Error appears here
...
``````

But in this case that is probably not the way to solve your issue.

The problem is that integral and fractional numbers are fundamentally incompatible. You can’t use `mod` with fractional numbers and you can’t use `(/)` with integral numbers.

There are two alternatives I can think of:

1. You can use `div` instead of `(/)` to divide integral numbers, but this rounds the result down.
2. You can use `mod'` instead of `mod` to work on fractional (actually `Real`) numbers.
2 Likes

Can you give a complete program in another language that uses this approach? I don’t see how that would work in this situation.

Edit: To clarify, in this case I believe you don’t want to dispatch based on the type, instead you want to dispatch on the operator used in the input. What if the type is an instance of `Integral` (`Integral` is a constraint, not a type) while the input operation is `/`?

A good question and I was seeing that Integral is a constraint, not a type by the errors I was getting while writing code, but it wasn’t clicking in my head till you said it.

As for a complete example in another language I can’t and don’t have to sort of. In JavaScript you can check if a variable is a string or number but since since `number` covers all the number types you can’t differentiate between types of numbers.

But I wrote it in JS anyway. It just doesn’t care.

``````const getFn = str => {
switch (str) {
case '+':
return (a,b) => a + b
case '-':
return (a,b) => a - b
case '*':
return (a,b) => a * b
case '/':
return (a,b) => a / b
case '%':
return (a,b) => a % b
}
}

['+', '-', '*', '/', '%'].forEach(x =>{
const fn = getFn(x)
console.log(fn.toString())
console.log(fn(5,2))
})
``````

output

``````function (a, b) {
return a + b;
}
7
function (a, b) {
return a - b;
}
3
function (a, b) {
return a * b;
}
10
function (a, b) {
return a / b;
}
2.5
function (a, b) {
return a % b;
}
1
``````

I haven’t written C# since 2008 so I’m not even going to give it a try

And a bit of a math lesson for me.

I might have know that 30 years ago in college.

Given that and how long I have been playing around with the larger exercise, I think I’m going to drop modulus, and finish-up the rest of the exercise and move on.

You could do something similar to what you probably would want in other languages - convert to some integer type, do the `mod` and then convert back to Double/Float.

Like this:

``````getFn :: (Foldable t, RealFrac a) => t Char -> Either String (a -> a -> a, String)
getFn str
| '+' `elem` str = Right ((+), "+")
| '-' `elem` str = Right ((-), "-")
| '*' `elem` str = Right ((*), "*")
| '/' `elem` str = Right ((/), "/")
| '%' `elem` str = Right (\x y -> fromIntegral (truncate x `mod` truncate y), "%")
| otherwise = Left "Invalid operator. Must be one of +, -, *, /, %"
``````

here some example output:

``````ghci> Right (f, _) = getFn "+"
ghci> f 3.5 6.6
10.1
ghci> Right (f, _) = getFn "%"
ghci> f 19.0 7.0
5.0
``````

of course `truncate` might not what you want but this is close to the usual type-casts in C-like languages.

Out of the box this will work with both `Double` and `Float` (those should be the instances of `RealFrac` you get with base).