模式匹配与构造函数

时间:2016-04-16 10:35:49

标签: haskell

我有两个几乎相同的函数用于不同的数据构造函数,并想知道是否有可能统一两者。一个简约的例子是以下

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

data T a = T1 a | T2 Int | T3

f_t :: T a -> a -> a
f_t  (T1 x) _ = x
f_t  _      x = x

这种方法只能定义一个由类型构造函数(Maybe或T)和数据构造函数(Just或T1)参数化的函数吗?

3 个答案:

答案 0 :(得分:6)

为数据类型实施Foldable实例后,此提示可以表示为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

您甚至可以让generic-deriving个软件包为您推导出上述Foldable个实例:

{-# 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类型的值。如果数据类型过于复杂,多个构造函数包含一个或多个{{1} },你最好手动完成它或仔细检查那个软件包派生的内容)

ghci的一些结果:

a

答案 1 :(得分:3)

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

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

答案 2 :(得分:3)

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

问问自己这个统一功能的类型签名是什么样的? 类型签名代表功能背后的想法。 MaybeT有哪些内容 在这种情况下有共同点,这样你就可以统一起作用的功能 他们?你想要建立什么样的抽象?

所有这些事情都不清楚你的问题。如果你的想法是公正的 切割样板(这不是样板),然后不要尝试 统一不同的东西只是为了缩短代码,你会得到 最终令人困惑的事情。

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