Haskell: 是否可以定义一个数据类型来封装 Maybe、String 和 Double 并具有应用应用值的能力?

Haskell: Is it possible to define a datatype that can encapsulate Maybe, String & Double with ability to apply value applicatively?

我是一个 Haskell 初学者,在构建一个简单的项目时遇到了这个奇怪的问题。

我有一个函数列表,例如

[f1, f2, f3 ... fn] 

这不起作用,因为它们的类型不同。有些有 Ct -> StringCt -> DoubleCt -> Maybe Double

我想做的是像这样应用这些函数

[f1, f2, f3 ... fn] <*> [v1, v2, v3 ... vn] 

其中所有 v 的类型相同 Ct

这个问题可以通过像

这样的元组使用列表理解来轻松解决

[(f1 a, f2 a, f3 a ... fn a) | a <- [v1, v2, v3 ... vn]]

看起来像这样

[ (f1 v1, f2 v1, f3 v1, f4, v1 ... fn v1)

, (f2 v1, f2 v2, f3 v2, f4 v2 ... fn v2)

, ...

, (fn v1, fn v2, fn v3, fn v4 ... fn vn)

]

但是 n 是一个相当大的数字,您必须定义一个单独的 show 实例才能在终端上打印它们,这是我想做的事情之一。

我知道克服这个问题的几种方法,一种是使用元组,但将结果分成更小的块,但我想知道,是否有一种方法可以定义一种数据类型,它可以封装多种数据类型并仍然保留 'idiomaticity' 和应用风格的可读代码?

创建三个列表,类型为 [Ct -> String][Ct -> Double][Ct -> Maybe Double]。每个都可以应用到您的 [Ct] applicatively。

想到了两个备选解决方案,但立即被丢弃:一种新的数据类型,可以容纳 StringDoubleMaybe Double 中的任何一个;或存在主义,它们本质上只是对同一想法的更统一的包装。想法一看起来像这样:

data Weird
    = It'sAString String
    | It'sADouble Double
    | It'sAMaybe (Maybe Double)

然后您将使用例如[It'sAString . f1, It'sADouble . f2, It'sAMaybe . f3],其类型为 [Ct -> Weird],可以应用使用。对我来说,这似乎已经超出了它的价值,特别是考虑到您的消费者现在必须准备好处理这三个构造函数中的任何一个。

存在主义的方式会更糟:你想要识别(或创建)一个 class,它涵盖了你想用 StringDouble,或 Maybe Double,它首先明智地统一了所有三种类型。哎哟。要使它有意义,您可能想要做的事情太多了。