将返回类型约束到Context

时间:2010-07-03 10:24:24

标签: haskell typeclass

到目前为止,我的尝试是:

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

我想测试编译。我认为问题不在于普遍量化。 ghc说a是'严格类型变量'编辑刚性类型变量),但我真的不理解这是什么。这个问题似乎与this

有关

修改

正如我在@ sepp2k的评论中写的那样,它可能与存在主义类型有关,但我偶然发现了一个奇怪的行为:

编译:

{-# 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

但这不是('a'是刚性类型变量消息)

{-# 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

那是因为1 ::(Num t)=>吨。我能定义一些东西(typeconstructor,consts dunno)吗?

2 个答案:

答案 0 :(得分:5)

当我取消注释test的定义并尝试编译代码时,我得到“模糊的类型变量”。严格要求。要理解这个含糊不清的原因,请考虑一下:

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?

当然在您的代码中只有一个Footable实例,因此haskell理论上可以推断您要使用为foo2定义的FooT,因为这是范围内唯一的实例。但是,如果它这样做,一旦导入恰好定义另一个Footable实例的模块,代码就会中断,因此haskell不这样做。

要解决您的问题,您需要使用类似的类型注释foo2:

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)

要求所有Footables都是Show and Read的实例,只需执行以下操作:

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

就像你在评论中所做的那样,但没有在foo2的签名中再次指定约束。

答案 1 :(得分:2)

正如sepp2k所说,Ghc无法猜测foo2的返回类型。约束它(这是你的问题的标题)添加内联类型签名。

  

test = print(foo2 :: FooT)