Non polymorphic numerals option -- avoiding type classes

In haskell, we have Prelude> :t 4 4 :: Num a => a Prelude> This may be nice in its generality but it makes it hard (for me at least) when teaching a beginners course to teach polymorphic vs monomorphic types. The above leads to even more 'advanced' results like this: Prelude> :t [[1],2] [[1],2] :: (Num [t], Num t) => [[t]] Prelude> [[1],2] <interactive>:5:6: No instance for (Num [t0]) arising from the literal `2' Possible fix: add an instance declaration for (Num [t0]) In the expression: 2 In the expression: [[1], 2] In an equation for `it': it = [[1], 2] By contrast in gofer, numeric literals are monomorphic and no such peculiarities arise ? :t [[1],2] ERROR: Type error in list *** expression : [[1],2] *** term : 2 *** type : Int *** does not match : [Int] [[1],2] ERROR: Type error in list *** expression : [[1],2] *** term : 2 *** type : Int *** does not match : [Int] So is there any set of flags to make haskell literals less polymorphic? ie I want 3 to have type Int and 3.0 to have type Float. This is of course for beginning students to not see type classes too early

You should note that GHCi uses extended defaulting rules as explained in [1]. This means that a literal like 5 will only be of type Num a => a in GHCi while in a normal Haskell program it will default to some concrete type (Integer if there are no other constraints). Also, if you define x = 5 in a .hs file and load the file in GHCi, x will have type Integer. In my short search I could not find out how to reverse this behavior, :unset -XExtendedDefaultRules does not seem to work.

Sorry, forgot the link: http://www.haskell.org/ghc/docs/7.0.4/html/users_guide/interactive-evaluatio... Section 2.4.5 Type defaulting in GHCi

* Rustom Mody
So is there any set of flags to make haskell literals less polymorphic?
Yes, there is! % ghci -XRebindableSyntax GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done.
import Prelude hiding (fromInteger) Prelude> let fromInteger = id Prelude> :t 3 3 :: Integer
Roman

On Thu, Dec 27, 2012 at 1:48 AM, Roman Cheplyaka
* Rustom Mody
[2012-12-26 20:12:17+0530] So is there any set of flags to make haskell literals less polymorphic?
Yes, there is!
% ghci -XRebindableSyntax GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done.
import Prelude hiding (fromInteger) Prelude> let fromInteger = id Prelude> :t 3 3 :: Integer
Roman
Thanks Roman -- that helps. And yet the ghci error is much more obscure than the gofer error: --- contents of .ghci --- :set -XRebindableSyntax let fromInteger = id ------ ghci session ----- $ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :t 5 5 :: Integer Prelude> :t [[1,2],3] <interactive>:1:8: Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3] ----- The same in gofer ----- Gofer session for: pustd.pre ? :t [[1,2],3] ERROR: Type error in list *** expression : [[1,2],3] *** term : 3 *** type : Int *** does not match : [Int] -------------- So the error is occurring at the point of the fromInteger (= id) but the message does not indicate that -- http://www.the-magus.in http://blog.languager.org

Prelude> :t [[1,2],3]
you have a list with 2 elements:
- [1,2]
- 3
the type of [1,2] is [Integer]
the type of 3 is Integer
But all elements in a list must have the same type.
2012/12/27 Rustom Mody
On Thu, Dec 27, 2012 at 1:48 AM, Roman Cheplyaka
wrote: * Rustom Mody
[2012-12-26 20:12:17+0530] So is there any set of flags to make haskell literals less polymorphic?
Yes, there is!
% ghci -XRebindableSyntax GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done.
import Prelude hiding (fromInteger) Prelude> let fromInteger = id Prelude> :t 3 3 :: Integer
Roman
Thanks Roman -- that helps. And yet the ghci error is much more obscure than the gofer error:
--- contents of .ghci --- :set -XRebindableSyntax let fromInteger = id ------ ghci session ----- $ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :t 5 5 :: Integer Prelude> :t [[1,2],3]
<interactive>:1:8: Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3]
----- The same in gofer ----- Gofer session for: pustd.pre ? :t [[1,2],3]
ERROR: Type error in list *** expression : [[1,2],3]
*** term : 3 *** type : Int *** does not match : [Int] -------------- So the error is occurring at the point of the fromInteger (= id) but the message does not indicate that
-- http://www.the-magus.in http://blog.languager.org
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe

Hi David, it looks like Rustom's aware that haskell's not lisp. What he
really wants methinks is a way to suppress type classes altogether! That or
a NoOverloadedNumerals extension.
-- Kim-Ee
On Thu, Dec 27, 2012 at 4:03 PM, David Virebayre wrote: Prelude> :t [[1,2],3] you have a list with 2 elements:
- [1,2]
- 3
the type of [1,2] is [Integer]
the type of 3 is Integer But all elements in a list must have the same type. 2012/12/27 Rustom Mody On Thu, Dec 27, 2012 at 1:48 AM, Roman Cheplyaka * Rustom Mody So is there any set of flags to make haskell literals less wrote:
polymorphic? Yes, there is! % ghci -XRebindableSyntax
GHCi, version 7.6.1: http://www.haskell.org/ghc/ :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done. import Prelude hiding (fromInteger)
Prelude> let fromInteger = id
Prelude> :t 3
3 :: Integer Roman Thanks Roman -- that helps.
And yet the ghci error is much more obscure than the gofer error: --- contents of .ghci ---
:set -XRebindableSyntax
let fromInteger = id
------ ghci session -----
$ ghci
GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :t 5
5 :: Integer
Prelude> :t [[1,2],3] <interactive>:1:8:
Couldn't match expected type `[Integer]' with actual type `Integer'
Expected type: Integer -> [Integer]
Actual type: Integer -> Integer
In the expression: 3
In the expression: [[1, 2], 3] ----- The same in gofer -----
Gofer session for:
pustd.pre
? :t [[1,2],3] ERROR: Type error in list
*** expression : [[1,2],3] *** term : 3
*** type : Int
*** does not match : [Int]
--------------
So the error is occurring at the point of the fromInteger (= id) but the
message does not indicate that --
http://www.the-magus.in
http://blog.languager.org _______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe _______________________________________________
Haskell-Cafe mailing list
Haskell-Cafe@haskell.org
http://www.haskell.org/mailman/listinfo/haskell-cafe

On Thu, Dec 27, 2012 at 8:26 PM, Kim-Ee Yeoh
Hi David, it looks like Rustom's aware that haskell's not lisp. What he really wants methinks is a way to suppress type classes altogether! That or a NoOverloadedNumerals extension.
-- Kim-Ee
I'm not really sure about that... Look! ghci with default startup -------------------- $ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :t [[1,2],3] [[1,2],3] :: (Num [t], Num t) => [[t]] So it would appear that ghci is giving a well-typing for [[1,2], 3]. But is it? Prelude> [[1,2],3] <interactive>:3:8: No instance for (Num [t0]) arising from the literal `3' Possible fix: add an instance declaration for (Num [t0]) In the expression: 3 In the expression: [[1, 2], 3] In an equation for `it': it = [[1, 2], 3] ------------------- So is it well-typed in ghci or not?? And now we add Roman's suggestions... $ cat .ghci :set -XRebindableSyntax let fromInteger = id And run ghci again $ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :t [[1,2],3] <interactive>:1:8: Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3] Prelude> [[1,2],3] <interactive>:3:8: Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3] Prelude> So far so good -- when an expression is type-wrong, its 'wrongness' is the same irrespective of whether I ask for its type or evaluate it. But now we are in for new surprises: Try out f x y = x / y Prelude> :l f [1 of 1] Compiling Main ( f.hs, interpreted ) f.hs:1:11: Not in scope: `/' Failed, modules loaded: none. Prelude> (/) Oh is it that now integer literals are just plain Integers and cant be divided using '/' ?? So lets replace '/' with '+' f.hs:1:11: Not in scope: `+' And now I am at my wits end!

I don't know about the RebindableSyntax extension. But Prelude> :t [[1,2],3] [[1,2],3] :: (Num [t], Num t) => [[t]] The above only says that is is possible to have a list like [[1,2],3] if you have for a Num t, [t] is also an instance of Num. But it doesn't guarantee the existence of such an instance. When you actually execute the code then you see that no such instance exists by default. -Satvik

* Rustom Mody
But now we are in for new surprises: Try out f x y = x / y Prelude> :l f [1 of 1] Compiling Main ( f.hs, interpreted )
f.hs:1:11: Not in scope: `/' Failed, modules loaded: none. Prelude> (/)
It's because RebindableSyntax implies NoImplicitPrelude. This is not an issue if you only work in the interpreter (you can put "import Prelude hiding (fromInteger)" in .ghci), but you'd also need to put that into every source file that you wish to load. An alternative would be to create your own Prelude (or use an existing one, like [1]) and use it instead of the one defined in base (by hiding base and exposing a different package). [1]: http://hackage.haskell.org/packages/archive/simpleprelude/1.0.1.3/doc/html/P... Roman

Forgot to say: if you go the first route, you'll also need to define your
fromInteger in every module — the one from .ghci won't be in scope.
You can define
module MyPrelude (module Prelude, fromInteger) where
import Prelude hiding (fromInteger)
fromInteger = id
and import it instead.
* Roman Cheplyaka
* Rustom Mody
[2012-12-27 22:18:15+0530] But now we are in for new surprises: Try out f x y = x / y Prelude> :l f [1 of 1] Compiling Main ( f.hs, interpreted )
f.hs:1:11: Not in scope: `/' Failed, modules loaded: none. Prelude> (/)
It's because RebindableSyntax implies NoImplicitPrelude. This is not an issue if you only work in the interpreter (you can put "import Prelude hiding (fromInteger)" in .ghci), but you'd also need to put that into every source file that you wish to load.
An alternative would be to create your own Prelude (or use an existing one, like [1]) and use it instead of the one defined in base (by hiding base and exposing a different package).
[1]: http://hackage.haskell.org/packages/archive/simpleprelude/1.0.1.3/doc/html/P...
Roman

On Thu, Dec 27, 2012 at 11:48 PM, Rustom Mody
On Thu, Dec 27, 2012 at 8:26 PM, Kim-Ee Yeoh
wrote: What he really wants methinks is a way to suppress type classes altogether! That or a NoOverloadedNumerals extension.
I'm not really sure about that... Look!
Prelude> :t [[1,2],3] [[1,2],3] :: (Num [t], Num t) => [[t]]
As Satvik explained, well-typed does not imply instantiable. And with constraints, not instantiable /does/ imply not evaluable!
:set -XRebindableSyntax let fromInteger = id Prelude> :t [[1,2],3]
Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3]
You can see overloaded numerals at work again via the hidden hand of
fromInteger.
Presumably some imaginary NoOverloadedNumerals extension would thoroughly
purge its presence.
-- Kim-Ee
On Thu, Dec 27, 2012 at 11:48 PM, Rustom Mody
On Thu, Dec 27, 2012 at 8:26 PM, Kim-Ee Yeoh
wrote: Hi David, it looks like Rustom's aware that haskell's not lisp. What he
-- Kim-Ee
I'm not really sure about that... Look!
ghci with default startup --------------------
$ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :t [[1,2],3] [[1,2],3] :: (Num [t], Num t) => [[t]]
So it would appear that ghci is giving a well-typing for [[1,2], 3]. But is it?
Prelude> [[1,2],3]
<interactive>:3:8:
No instance for (Num [t0]) arising from the literal `3'
Possible fix: add an instance declaration for (Num [t0]) In the expression: 3 In the expression: [[1, 2], 3] In an equation for `it': it = [[1, 2], 3] ------------------- So is it well-typed in ghci or not??
And now we add Roman's suggestions... $ cat .ghci
:set -XRebindableSyntax let fromInteger = id
And run ghci again
$ ghci GHCi, version 7.4.1: http://www.haskell.org/ghc/ :? for help Loading package ghc-prim ... linking ... done. Loading package integer-gmp ... linking ... done. Loading package base ... linking ... done. Prelude> :t [[1,2],3]
<interactive>:1:8: Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3] Prelude> [[1,2],3]
<interactive>:3:8:
Couldn't match expected type `[Integer]' with actual type `Integer' Expected type: Integer -> [Integer] Actual type: Integer -> Integer In the expression: 3 In the expression: [[1, 2], 3] Prelude>
So far so good -- when an expression is type-wrong, its 'wrongness' is
really wants methinks is a way to suppress type classes altogether! That or a NoOverloadedNumerals extension. the same irrespective of whether I ask for its type or evaluate it.
But now we are in for new surprises: Try out f x y = x / y Prelude> :l f [1 of 1] Compiling Main ( f.hs, interpreted )
f.hs:1:11: Not in scope: `/' Failed, modules loaded: none. Prelude> (/)
Oh is it that now integer literals are just plain Integers and cant be
divided using '/' ??
So lets replace '/' with '+' f.hs:1:11: Not in scope: `+'
And now I am at my wits end!
participants (6)
-
David Virebayre
-
Kim-Ee Yeoh
-
koomi
-
Roman Cheplyaka
-
Rustom Mody
-
satvik chauhan