Return type restriction in context

Here are my attempts:

module Main where data FooT = One | Two deriving (Show, Read) {- That is what I want foo :: (Show a, Read a) => a foo = One -} --class Footable (Show a, Read a) => a where class Footable a where --foo2 :: (Show a, Read a) => a foo2 :: a instance Footable FooT where foo2 = One -- test = print foo2 

I want the test to compile. I do not think the problem revolves around universal quantification. ghc says that a is a strict variable of type edit (a hard variable of type), but I really don't understand what it is. The question seems to be related to this.

Edit

As I wrote in my comment @ sepp2k, this is probably about the existential type, but I came across a curious behavior:

This compiles:

 {-# LANGUAGE OverlappingInstances, FlexibleInstances, OverlappingInstances, UndecidableInstances, MonomorphismRestriction, PolymorphicComponents #-} {-# OPTIONS_GHC -fno-monomorphism-restriction #-} module Main where class (Num a) => Numable a where foo2 :: a instance (Num a) => Numable a where foo2 = 1 instance Numable Int where foo2 = 2 instance Numable Integer where foo2 = 3 --test = foo2 + foo2 -- This does NOT compile (ambiguous a) test = (foo2::Integer) + foo2 --this works 

but it’s not (`a 'is a message of a variable of hard type)

 {-# LANGUAGE OverlappingInstances, FlexibleInstances, OverlappingInstances, UndecidableInstances, MonomorphismRestriction, PolymorphicComponents #-} {-# OPTIONS_GHC -fno-monomorphism-restriction #-} module Main where data FooT = One | Two deriving (Show, Read) data BarT = Ten deriving (Show, Read) class (Show a, Read a) => Footable a where foo2 :: a instance (Show a, Read a) => Footable a where foo2 = Ten instance Footable FooT where foo2 = One main = print foo2 

so 1 :: (Num t) => t. Can I define something (typeconstructor, consts dunno)?

+4
source share
2 answers

When I uncomment the definition of test and try to compile your code, I get an "ambiguous type variable". Nothing about rigor. To understand why this is ambiguous, consider this:

 module Main where data FooT = One | Two deriving (Show, Read) data BarT = Three | Four deriving Show class Footable a where foo2 :: a instance Footable FooT where foo2 = One instance Footable BarT where foo2 = Three main = print foo2 -- Should this print One or Three? 

Of course, there is only one instance of Footable in your code, so haskell could theoretically suggest that you want to use foo2 defined for FooT because it is the only instance in the scope. However, if this happens, the code will break as soon as you import a module that will define another instance of Footable, so haskell does not.

To fix your problem, you need to annotate foo2 with your type:

 module Main where data FooT = One | Two deriving (Show, Read) class Footable a where foo2 :: a instance Footable FooT where foo2 = One main = print (foo2 :: FooT) 

To require all Footables to be instances of Show and Read, simply do:

 class (Show a, Read a) => Footable a where foo2 :: a 

As in your comments, but without specifying a restriction again in the signature foo2.

+5
source

As sepp2k said, Ghc cannot guess the return type of foo2. Limit it (this is the name of your question), add a signature of the built-in type.

test = print (foo2 :: FooT)

+2
source

Source: https://habr.com/ru/post/1314614/


All Articles