haskell - 将返回类型限制为 Context

标签 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) => 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 理论上可以推断您想要使用 foo2FooT 定义因为这是范围内的唯一实例。但是,如果它这样做了,一旦你导入一个恰好定义另一个 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/

相关文章:

Haskell 相当于 C 的 __LINE__

haskell - Haskell 中的 Y 组合器、无限类型和匿名递归

haskell - 无法推断因使用 ‘>’ 而产生的 (Ord a0)

haskell - 解决重载函数的歧义

haskell - GHC 如何使用 Num 实例将多态数字文字转换为任意类型?

list - Haskell:在抽象数据类型上使用映射的问题

haskell - 函数调用后秒差距意外字符

列表到元组计数值重复和元组内的列表 - Haskell

scala - 如何重载类型类的产品方法

haskell - 派生类型及其依赖项