模式和构造函数之间的“主要”区别是什么 - Haskell

时间:2012-12-28 12:39:55

标签: haskell

模式和构造函数之间的“主要”区别是什么?

答案:

With a constructor you can add a tag to your data, in such a way that it receives a type.

Patters will be more used for matching data with a pattern, which isn't the case of a constructor. 
Patters can also be used for the destruction reasons.

2 个答案:

答案 0 :(得分:7)

正如Daniel Fisher所说,构造函数构建了一些价值,模式将它分开:

data Person = P String String Int

-- constructor to build a value
makePerson firstname lastname age = P firstname lastname age 

-- pattern to take a value apart
fullName (P firstname lastname _) = firstname ++ " " + lastname 

请注意,这只是一个示例,对于此特定类型,记录语法更合适。

答案 1 :(得分:5)

在某种意义上,它们彼此非常相似,因为它们是双重的。构造函数可以被认为是数据类型的签名函子的代数,并在同一个函子上模式化代数。

为了更明确,让我们考虑一下[]。它的签名函子是T_A X = 1 + A * X或者在Haskell中

type ListF a x = Maybe (a, x)

有明显的Functor实例。我们可以看到ListF - 带List运营商的代数只是其构造函数

-- general definition
type Algebra f a = f a -> a

consList :: Algebra (ListF a) [a]
consList Nothing        = []
consList (Just (a, as)) = a:as

双重地,我们可以查看以ListF为载体的List的代数

type Coalgebra f a = a -> f a

unconsList :: Coalgebra (ListF a) [a]
unconsList []     = Nothing
unconsList (a:as) = Just (a, as)

进一步看到headtail的安全版本是[]上非常自然的析构函数

headMay :: [a] -> Maybe a
headMay = fmap fst . unconsList

tailMay :: [a] -> Maybe a
tailMay = fmap snd . unconsList

这引发了个人对headtail的不满,甚至没有特别好的功能而忽略了他们的偏见 - 他们只是在具有签名仿函数的无限列表中很自然T A X = A*X

现在在Haskell中,一个仿函数的initial Algebra and final Coalgebra与该仿函数的定点一致

newtype Fix f = Fix { unfix :: f (Fix f) }

究竟是什么数据类型。我们可以证明[a]Fix (ListF a)

同构
fwd :: [a] -> Fix (ListF a)
fwd []     = Fix Nothing
fwd (a:as) = Fix (Just (a, fwd as))

bwd :: Fix (ListF a) -> [a]
bwd (Fix Nothing)           = []
bwd (Fix (Just (a, fixed))) = a : bwd fixed

这为使用数据类型本身作为构造函数和模式提供了理由,但如果您创建其他类型的“类似代数”的东西,那么您可以拥有一流的模式,例如She提供的模式或pattern combinators

为了更深入地理解模式和构造函数的二元性,请尝试使用类似

的数据类型再次执行此练习
data Tree a = Leaf | Branch (Tree a) a (Tree a)

它的签名函子是T A X = 1 + X*A*X

type TreeF a x = Maybe (x,a,x)