给定:
data TwoInts = TwoInts Int Int
add'em :: TwoInts -> Int
add'em (TwoInts a b) = a+b
是否有可能写出不需要命名a
和b
的add'em
函数。例如:
add'em TwoInts = (+) -- (Note: Fails to type check)
给定:
data TwoInts = TwoInts Int Int
add'em :: TwoInts -> Int
add'em (TwoInts a b) = a+b
是否有可能写出不需要命名a
和b
的add'em
函数。例如:
add'em TwoInts = (+) -- (Note: Fails to type check)
类比元组,
data TwoInts = TwoInts { fst', snd' :: Int }
我们可以定义一个操作,将接受两个参数的函数提升到 TwoInt
上。
uncurry' f p = f (fst' p) (snd' p)
给我们提供了美好的符号表示:add'em = uncurry' (+)
uncurry = ('ap' snd) . (. fst)
。关键是要摆脱模式匹配。 - Don Stewartuncurry f = f <$> fst <*> snd
-- 比愚蠢的(.)
版本简单得多。 - Don Stewartf . fst <*> snd
,因为打字速度更快。在此选择的 Applicative 实例中,<*> 有点像 FORTH 等基于堆栈的语言中的 DUP。 - Robin Greenmapf f (Type val) = Type (f val)
函数,类似于 fmap,然后不导出它。你可以通过传递更多函数来为 n 元数据类型做同样的事情。如果实现不应该是秘密的,你也可以导出它(作为一元的 fmap)。对于复杂类型,我建议使用这种 map 函数或视图,因为模式匹配会将你与实现绑定在一起。maybe
和 either
。