gpt4 book ai didi

haskell - 如何处理多参数类型类的功能,谁不需要类型类的每种类型?

转载 作者:行者123 更新时间:2023-12-01 07:00:26 24 4
gpt4 key购买 nike

我已经定义了一个类似于接口(interface)的类型类,其中包含我的程序所需的一堆函数。遗憾的是,它需要多种多态类型,但并不是这个多参数类型类的每个函数都需要每种类型。 GHC 用无法推断的类型困扰着我,我无法让代码运行。

一个简化的例子:

{-# LANGUAGE MultiParamTypeClasses #-}

class Foo a b where
-- ...
bar :: a -> ()

baz :: Foo a b => a -> ()
baz = bar

GHC 说

Possible fix: add a type signature that fixes these type variable(s)

我该如何为 b 执行此操作?尤其是当我想保留 b多态的。仅 Foo 的一个实例应该定义这个类型是什么。

最佳答案

这是不可能的。

根本问题是多参数类型类依赖于每个类型参数。如果类中的特定定义不使用每个类型参数,编译器将永远无法知道您的意思是什么实例,您甚至无法指定它。考虑以下示例:

class Foo a b where
bar :: String -> IO a

instance Foo Int Char where
bar x = return $ read x

instance Foo Int () where
bar x = read <$> readFile x

这两个实例使用它们的参数做完全不同的事情。编译器必须选择其中一个实例的唯一方法是匹配两个类型参数。但是没有办法指定类型参数是什么。这门课简直糟透了。没有办法调用 bar函数,因为您永远无法为编译器提供足够的信息来解析要使用的类实例。

那么为什么类定义没有被编译器拒绝呢?因为您有时可以通过 FunctionalDependencies 使其工作。扩大。

如果一个类有多个参数,但它们是相关的,则有时可以将该信息添加到类的定义中,从而允许类成员不使用类定义中的每个类型变量。
class Foo a b | a -> b where
bar :: String -> IO a

使用该定义(需要 FunctionalDependencies 扩展名),您告诉编译器对于 a 的任何特定选择,只有一个有效的选择 b .尝试定义上述两个实例都会出现编译错误。

鉴于此,编译器知道它可以选择 Foo 的实例。仅基于类型 a 使用.在这种情况下, bar可以调用。

关于haskell - 如何处理多参数类型类的功能,谁不需要类型类的每种类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23983374/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com