本文介绍了有条件地派生Show对于在类型构造函数上参数化的存在类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

$ $ p $ $ $ $ $ $ $ $ $ b $ { a = forall b。显示b => X(ab)

我想派生 Show(X a),但我当然只能在 Show(ab)的实例中这样做。我很想写

  { - #LANGUAGE StandaloneDeriving# - } 
导出实例Show(ab)=> ;显示(X a)

但不幸的是,类型变量 b

我的下一个尝试是将 Show(ab)移动到实例上下文中,因为它受到全部绑定。

上下文到数据类型定义中的所有内容中,如下所示:

  data X a = forall b 。 Show(a b)=> X(ab)
导出实例Show(X a)

我失去了用一个难以显示的(ab)构造 X 的能力。



有没有办法允许 X 用任何(ab)构造,然后仅当(ab)可显示时有条件地派生 Show(X a)

解决方案

这是Prelude类的一个缺陷。尽管体现在 prelude-extras 包。我将在下面概述它。



我们希望创建一个更高级的 Show 类。它看起来像这样

  class Show1 a where 
show1 :: Show b => a b - >字符串

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

 派生实例Show1 a =>显示(X a)

不幸的是,编译器还没有足够的信息来实现这个派生。我们需要证明(Show b,Show1 a)足以导出 Show(a b)。为了做到这一点,我们需要启用一些(可怕的,但是非常有用的)扩展

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

instance(Show b,Show1 a)=>显示(ab)其中
show = show1

现在我们已经证明了编译器将能够推导出我们需要的数据。b b

  data X a = forall b。显示b => X(a b)
导出实例Show1 a =>显示(X a)


Suppose I have a data type like this:

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

I would like to derive Show (X a), but of course I can only do so if there is an instance of Show (a b). I'm tempted to write

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

but unfortunately the type variable b is not available in the instance context because it is bound by the forall.

My next attempt was to move the Show (a b) context into the forall in the data type definition, like so:

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

This compiles, but unfortunately now I've lost the ability to construct an X with an unshowable (a b).

Is there any way to allow X to be constructed with any (a b), and then conditionally derive Show (X a) only if (a b) is showable?

解决方案

This is a deficiency in the Prelude classes. There's a nice way around it though embodied in the prelude-extras package. I'll outline it below.

We'd like to create a higher-kinded Show class. It looks like this

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

Then we can at least accurately express our desired constraint like

deriving instance Show1 a => Show (X a)

Unfortunately, the compiler does not yet have enough information to achieve this derivation. We need to show that (Show b, Show1 a) is enough to derive Show (a b). To do so we'll need to enable some (scary, but sanely-used) extensions

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

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

And now that we have that proof the compiler will be able to derive what we need

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

这篇关于有条件地派生Show对于在类型构造函数上参数化的存在类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

11-03 03:04