将返回类型约束到Context

sup*_*tux 4 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
Run Code Online (Sandbox Code Playgroud)

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

编辑

正如我在@ 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
Run Code Online (Sandbox Code Playgroud)

但这不是('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
Run Code Online (Sandbox Code Playgroud)

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

sep*_*p2k 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?
Run Code Online (Sandbox Code Playgroud)

当然在你的代码中只有一个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)
Run Code Online (Sandbox Code Playgroud)

要求所有Footables都是Show和Read的实例,只需:

class (Show a, Read a) => Footable a where
  foo2 :: a
Run Code Online (Sandbox Code Playgroud)

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

  • @ony:无法为用户定义的类型类定义默认值. (2认同)