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