5

In a source file:

addV1 x y = (if x > y then y else x) + 5
addV2 = \x -> \y -> (if x > y then y else x) + 5

In ghci:

ghci> :l h.hs
ghci> addV1 4.5 10

<interactive>:1083:1: warning: [-Wtype-defaults]
    • Defaulting the following constraints to type ‘Double’
        (Show a0) arising from a use of ‘print’ at <interactive>:1083:1-12
        (Ord a0) arising from a use of ‘it’ at <interactive>:1083:1-12
        (Fractional a0)
          arising from a use of ‘it’ at <interactive>:1083:1-12
    • In a stmt of an interactive GHCi command: print it
9.5
ghci> addV2 4.5 10

<interactive>:1084:7: error:
    • No instance for (Fractional Integer)
        arising from the literal ‘4.5’
    • In the first argument of ‘addV2’, namely ‘4.5’
      In the expression: addV2 4.5 10
      In an equation for ‘it’: it = addV2 4.5 10

I did get the following warnings when I loaded the source file:

h.hs:10:1: warning: [-Wmissing-signatures]
    Top-level binding with no type signature:
      addV1 :: (Num a, Ord a) => a -> a -> a
   |
10 | addV1 x y = (if x > y then y else x) + 5
   | ^^^^^

h.hs:11:1: warning: [-Wmissing-signatures]
    Top-level binding with no type signature:
      addV2 :: Integer -> Integer -> Integer
   |
11 | addV2 = \x -> \y -> (if x > y then y else x) + 5
   | ^^^^^

h.hs:11:46: warning: [-Wtype-defaults]
    • Defaulting the following constraints to type ‘Integer’
        (Num a0) arising from a use of ‘+’ at h.hs:11:46
        (Ord a0) arising from a use of ‘>’ at h.hs:11:27
    • In the expression: (if x > y then y else x) + 5
      In the expression: \ y -> (if x > y then y else x) + 5
      In the expression: \ x -> \ y -> (if x > y then y else x) + 5
   |
11 | addV2 = \x -> \y -> (if x > y then y else x) + 5
   |                                              ^
Ok, one module loaded.

Many thanks!

EDIT: It seems to be that when loading these functions from the source file, haskell is deciding that the second function should default to Integer. But when I define both these functions at the ghci command line, they both have the same type:

ghci> addV1 x y = (if x > y then y else x) + 5

<interactive>:1093:1: warning: [-Wname-shadowing]
    This binding for ‘addV1’ shadows the existing binding
      defined at h.hs:2:1
ghci> :t addV1
addV1 :: (Num a, Ord a) => a -> a -> a
ghci> addV2 = \x -> \y -> (if x > y then y else x) + 5

<interactive>:1095:1: warning: [-Wname-shadowing]
    This binding for ‘addV2’ shadows the existing binding
      defined at h.hs:3:1
ghci> :t addV2
addV2 :: (Num a, Ord a) => a -> a -> a

EDIT: When I add the type signature to the source file, both functions execute fine:

addV2 :: (Num a, Ord a) => a -> a -> a
addV2 = \x -> \y -> (if x > y then y else x) + 5

I'm just starting out with haskell. I guess the lesson I'm taking here is that it's important to always provide explicit type declarations, which is what I planned on doing anyway (just doing an exercise from a book).

Bruce
  • 2,406
  • 5
  • 29
  • 35
  • 2
    The dreaded [monomorphism restriction](https://stackoverflow.com/questions/32496864/what-is-the-monomorphism-restriction) strikes again. Put `{-# LANGUAGE NoMonomorphismRestriction #-}` at the top of the file to disable it (in GHCi it's already off by default). Or, even better, write an explicit type for your functions. You can read more about it on its own question, but just note that Haskell does not like to make `f = ...` polymorphic in the same way that it does with `f x = ...`, in absence of an explicit type. – chi Jun 27 '23 at 16:15
  • Super - thank you for the great response! – Bruce Jun 27 '23 at 16:25
  • 3
    I'd probably recommend *not* using `NoMonomorphismRestriction` in modules. The MR exists for a reason; it does tend to produce better results for "realistic" modules, even though it is annoying in toy examples like this (function with no type signature that is never used in the same module). However the MR really *cannot* produce good results in GHCi, which is why it is turned off by default there. So for learners I think getting used to it is better than making modules behave like GHCi. (Explicit type signatures on top-level functions stops it being a problem almost all of the time anyway) – Ben Jun 27 '23 at 16:41
  • Thanks @Ben , I will bear that in mind as I move forward. – Bruce Jun 27 '23 at 17:05
  • @Bruce: I suggest turning on the [`-Wmonomorphism-restriction` warning flag](https://ghc.gitlab.haskell.org/ghc/doc/users_guide/using-warnings.html#ghc-flag--Wmonomorphism-restriction). It’s not in the `-Wall` set because in typical code it can be a little noisy, but it’s very helpful for understanding the inferred type, and where you might want to add a type signature for a binding, or a type annotation for an expression. – Jon Purdy Jun 29 '23 at 18:09
  • @JonPurdy Ah great - thank you Jon! Will do. – Bruce Jun 30 '23 at 19:57

0 Answers0