tags:

views:

94

answers:

2

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, 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 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?

+4  A: 

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.

sepp2k
my idea was that if I constrain foo in that way foo :: (Show a, Read a) => a I could return various types without violating type-safety. (the 'strict type-variable' pops up when you uncomment the function foo). My class Footable was an attempt to solve problem. What I need are existential type or type-families.
supertux
When you do `main = print 3` it will specialize `3` to `Integer` type (even that the only required is `(Num a, Show a)`). Probably there is some way to define "defaults"
ony
@ony: There is no way to define defaults for user-defined typeclasses.
sepp2k
+2  A: 

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)

mb14
::FooT does not constrain to a context, but declares foo2 to be of the type FooT
supertux
which is what we want, don't we ?
mb14