类型类定义中的抽象数据类型

Gui*_*rel 3 haskell

我正在尝试了解s以下类型的情况:

class A a where
    f :: a -> s

data X = X

instance A X where
     f x = "anything"
Run Code Online (Sandbox Code Playgroud)

我希望这可以工作,认为因为类型s不受任何约束,它可以是任何东西.但编译器说它"无法将预期类型'与实际类型'[Char]'匹配",好像类型s是固定类型,如Int,Char ......

所以我的第二种解释就是说,因为我们s在类型类声明中什么都不知道,所以我们无法确定何时创建X一个实例,我们给出A的函数的返回值是否f匹配类型s.但是有些类使用的抽象数据类型没有绑定到任何没有问题的东西,比如Functor:

class Functor f where
    fmap :: (a -> b) -> f a -> f b 
Run Code Online (Sandbox Code Playgroud)

s当类型ab这里没有时,为什么类型高于问题?

lef*_*out 9

你试图表达这个:

    f :: a -> ?s . s
Run Code Online (Sandbox Code Playgroud)

......但你写的签名实际上是什么

    f :: a -> ?s . s
Run Code Online (Sandbox Code Playgroud)

所有这些意味着什么?

  • 存在类型 ?s . s的装置,该功能可以返回一个值某种类型的,即,"存在一个类型s,使得该函数返回一个s值".
    Haskell语言不支持这种做法,因为事实证明这种做法毫无用处.
  • 通用型 ?s . s是指,该功能能够产生一个值的任何类型的,即"所有类型s,函数可以返回一个s值".

后者非常有用; fmap实际上是一个很好的例子:该功能的工作,不管是什么类型的a,并b是,用户始终保证的结果实际上将有需要的类型,即f b.

但这意味着你不能像在实践中那样在实现中选择一些特定的类型String.......实际上,你可以这样做,但只能将存在主体包装在一个数据类型中:

{-# LANGUAGE ExistentialQuantification, UnicodeSyntax #-}

data Anything = ? s . Anything s

class A a where
  f :: a -> Anything

instance A X where
  f x = Anything "anything"
Run Code Online (Sandbox Code Playgroud)

...但正如我所说,这几乎完全无用,因为当有人想要使用该实例时,他们将无法知道包装结果值具有什么特定类型.对于完全未知类型的值,你无能为力.