gpt4 book ai didi

haskell - 有条件地派生 Show 以获取在类型构造函数上参数化的存在类型

转载 作者:行者123 更新时间:2023-12-02 16:40:10 25 4
gpt4 key购买 nike

假设我有这样的数据类型:

{-# LANGUAGE RankNTypes #-}
data X a = forall b. Show b => X (a b)

我想派生 Show (X a),但当然,只有存在 Show (a b) 实例时我才能这样做。我很想写

{-# LANGUAGE StandaloneDeriving #-}
deriving instance Show (a b) => Show (X a)

但不幸的是,类型变量 b 在实例上下文中不可用,因为它受 forall 绑定(bind)。

我的下一个尝试是将 Show (a b) 上下文移动到数据类型定义中的 forall 中,如下所示:

data X a = forall b. Show (a b) => X (a b)
deriving instance Show (X a)

它可以编译,但不幸的是现在我失去了用无法显示的 (a b) 构造 X 的能力。

有没有什么方法可以让X用任何(a b)来构造,然后有条件地只导出Show (X a)如果 (a b) 可以显示?

最佳答案

这是 Prelude 类的一个缺陷。尽管体现在 prelude-extras 中,但有一个很好的解决方法。包裹。我将在下面概述它。

我们想要创建一个更高级的 Show 类。看起来像这样

class Show1 a where
show1 :: Show b => a b -> String

那么我们至少可以准确地表达我们想要的约束,例如

deriving instance Show1 a => Show (X a)

不幸的是,编译器还没有足够的信息来实现这一推导。我们需要证明 (Show b, Show1 a) 足以导出 Show (a b)。为此,我们需要启用一些(可怕但使用正常的)扩展

{-# LANGUAGE FlexibleInstances         #-}
{-# LANGUAGE OverlappingInstances #-}

instance (Show b, Show1 a) => Show (a b) where
show = show1

现在我们有了证据,编译器将能够导出我们需要的内容

data X a = forall b . Show b => X (a b)
deriving instance Show1 a => Show (X a)

关于haskell - 有条件地派生 Show 以获取在类型构造函数上参数化的存在类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24482561/

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