Haskell 模式匹配与构造函数

Haskell 模式匹配与构造函数,haskell,Haskell,对于不同的数据构造函数,我有两个几乎相等的函数,我想知道是否有可能统一这两个函数。下面是一个极简主义的例子 f_maybe :: Maybe a -> a -> a f_maybe (Just x) _ = x f_maybe _ x = x 及 这是一种仅定义一个由类型构造函数(可能或T)和数据构造函数(只是或T1)同时进行参数化的函数的方法吗?一旦为数据类型实现了可折叠的实例,这个想法可以表示为foldr const data T a = T1 a | T2 In

对于不同的数据构造函数,我有两个几乎相等的函数,我想知道是否有可能统一这两个函数。下面是一个极简主义的例子

f_maybe :: Maybe a -> a -> a
f_maybe (Just x) _ = x
f_maybe _        x = x


这是一种仅定义一个由类型构造函数(可能或T)和数据构造函数(只是或T1)同时进行参数化的函数的方法吗?

一旦为数据类型实现了可折叠的实例,这个想法可以表示为
foldr const

data T a = T1 a | T2 Int | T3

instance Foldable T where
    -- if it's T1, it has a value
    foldMap f (T1 a) = f a
    -- if it's T2 or T3, it's considered "empty"
    foldMap f (T2 _) = mempty
    foldMap f T3     = mempty
您甚至可以让
通用派生
包为您派生上述
可折叠
实例:

{-# LANGUAGE DeriveGeneric #-}

import           Generics.Deriving.Foldable
import           GHC.Generics

data T a = T1 a | T2 Int | T3
    deriving (Generic1)

instance Foldable T where
    foldMap = gfoldMapdefault
(在您的情况下,实例并不含糊不清,因为只有一个构造函数可能恰好包含一个
a
类型的值。如果数据类型变得复杂,多个构造函数包含一个或多个
a
,您最好手动执行,或者仔细检查该包派生的内容)

以及ghci的一些结果:

-- `Maybe` already has the instance defined by the standard library
> foldr const 2 (Just 3)
< 3
> foldr const 2 Nothing
< 2

> foldr const 2 (T1 3)
< 3
> foldr const 2 (T2 10)
< 2
> foldr const 2 T3
< 2
--`Maybe`已经具有标准库定义的实例
>foldr const 2(仅3)
< 3
>foldr const 2无
< 2
>foldr const 2(T1 3)
< 3
>foldr const 2(T2 10)
< 2
>foldr const 2 T3
< 2

为了满足您的需要,两种类型都需要通过类型类共享一个公共接口。可以这样做:

class MyF mf where
    f :: mf a -> a -> a

instance MyF Maybe where
    f (Just x) _ = x
    f _        x = x

instance MyF T where
    f (T1 x) _ = x
    f _      x = x
示例:

f (Just 3) 3
3

f Nothing "Hello"
"Hello"

f (T1 5) 3
5

f (T2 20) 2
2

您可以编写一个统一的函数,该函数具有您想要的任何行为,并且可以在任何情况下工作 参数的类型,但如果没有具体数据,则无法进行模式匹配 构造函数(多态性),AFAIK


问问自己,这个统一函数的签名是什么样的? 类型签名代表函数背后的思想。你认为
可能
T
在这种情况下有一个共同点,这样您就可以统一工作的函数了 他们?您试图构建什么样的抽象

从你的问题来看,所有这些事情都不清楚。如果你的想法是 切掉样板(这并不是完全的样板),然后不要试图 统一不同的东西只是为了缩短代码,你会得到 最后有些令人困惑的事情

类型实际上应该是不同的,函数应该拒绝 类型错误,不能处理任何看起来有点相似的东西。也 多态代码通常不是一个好主意,因为可能会发生错误的代码 对类型检查器有一些意义,然后您将得到该程序
编译,但做了错误的事情。

一般来说,我们的想法是定义两种类型都实现的类型类
Foldable
恰好是用于示例函数的typeclass。非常感谢!我喜欢这个使用折叠的实现:)!然而,这只是一个简单的例子,我不确定是否同样适用于真实的例子(依赖于模式匹配)。你是对的。我还想到了一个类型类。但这样一来,基本上两个不同的定义又被使用了。恐怕你是对的——不同类型的不同构造函数不能直接统一。。。
f (Just 3) 3
3

f Nothing "Hello"
"Hello"

f (T1 5) 3
5

f (T2 20) 2
2