到目前为止,这是我的尝试:
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) => t。我可以像这样定义一些东西(类型构造函数,常量不知道)吗?
最佳答案
当我取消注释 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 和 Read 的实例,只需执行以下操作:
class (Show a, Read a) => Footable a where
foo2 :: a
就像您在评论中所做的那样,但没有在 foo2 的签名中再次指定约束。
关于haskell - 将返回类型限制为 Context,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3171179/