Here are my attempts so far:
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 test to compile. I don't think the problem revolves around universal quantification. ghc says that a is a 'strict type-variable' edit (rigid type variable) but I don't really comprehend what this is. The question seems to be related to this
Edit
As I wrote in my comment @sepp2k it's probably about the existential type but I have stumbled over a curious behaviour:
This does compile:
{-# LANGUAGE OverlappingInstances, Flex开发者_开发知识库ibleInstances, 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 this does not (`a' is a rigid type variable message)
{-# 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
that's so because 1 :: (Num t) => t. Can I define something (typeconstructor, consts dunno) like that?
When I uncomment the definition of test
and try to compile your code, I get "ambiguous type variable". Nothing about strictness. 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 in your code there is only one instance of Footable, so haskell could in theory infer that you want to use the foo2
defined for FooT
because that's the only instance in scope. However if it did that, the code would break as soon as you import a module that happens to define another instance of Footable, so haskell doesn't do that.
To fix your problem you need to annotate foo2 with its type like so:
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 that all Footables be instances of Show and Read simply do:
class (Show a, Read a) => Footable a where
foo2 :: a
Like you did in your comments, but without specifying the constraint again in the signature of foo2.
As sepp2k said, Ghc can't guess the return type of foo2. Do constraint it (which is the title of your question) add an inline type signature.
test = print (foo2 :: FooT)
精彩评论