haskell - 二元组的特殊地位是什么?

标签 haskell tuples

阅读真实世界 Haskell 和 Typeclassopedia我的印象是 2 元组 (a,b)在 Haskell 中可以有非常特殊的角色。

我遇到的第一个用途是 lookup我们使用 2 元组列表作为字典。

然后我也发现((,) e)是一个仿函数的实例(但没有其他 n 元组),例如在上述 (key,value) 的例子中是有意义的.

现在最新的案例——这是我真正想询问的案例——在 Typeclassopedia 的第 4.3 章中。那里说((,) a)Applicative 的一个实例如果 a是幺半群。你什么时候真正使用它?您使用 Applicative 的应用程序是什么? (a,b) 的实例?

最佳答案

没有什么可以阻止我们为三元组或任意 n 元组编写实例:

instance Functor ((,,) a b) where
  fmap f (x,y,z) = (x,y,f z)

instance (Monoid a, Monoid b) => Applicative ((,,) a b) where
  pure z              = (mempty,        mempty,          z)
  (a,b,f) <*> (x,y,z) = (a `mappend` x, b `mappend` y, f z)

对并不特殊,因此您可以为任何 n 元组实现实例。但由于这些实例必须写在某个地方,这就引出了我们应该走多远的问题。例如, Monoid 实例最多定义为 5 元组。当然可以为 10 元组编写它们,但此时我们只是复制样板代码。

话虽如此,对是特别的 因为它们的集合提供了一种描述关系的自然方式。一个例子是一本字典,它涉及一个术语及其定义:
dictionary :: [(String, String)]
dictionary =
  [("cat", "animal that likes strings; not Strings, though")
  ,("dog", "animal that likes you; yes you")
  ,("foo", "a strange word used by programmers in examples")
  ]

显示这种关系的另一种方式(如果所有对的第一部分都是唯一的)将是
partialDictionaryEntry :: String -> String

如果我们将输入域限制为 "cat" , "dog""foo" , 或者
dictionaryEntry :: String -> Maybe String

这正是\s -> lookup s dictionary将是。使用对,您可以对任何其他 n 元组进行建模:
(a,b,z)   = ((a,b),z)
(a,b,c,z) = ((a,b,c),z) = (((a,b),c),z)

从这个意义上说,它们是提供此功能的最小容器。我们可以从成对构建所有其他元组类型。哎呀,理论上我们甚至不需要写我们的 Applicative ((,,) a b)例如,因为它已经提供给 (,) (a,b)由于 Monoid实例。

话虽如此,为什么它甚至有 Applicative实例?这是最简单的Writer执行:
log :: (Show a) => a -> (String, a)
log x = (show x ++ "\n", x)

fivePlusThree = (+) <$> log 3 <*> log 5

main = do
  let (logs, result) = fivePlusThree
  putStrLn logs
  print result
3
5

8

这提供了一种向函数或值添加附加信息的简单方法,尽管您可能会使用 Writer和它的 writer方法,因为它们使用起来更愉快,并提供了严格的变体。

关于haskell - 二元组的特殊地位是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44780065/

相关文章:

haskell - 有没有办法在 Haskell 中取消映射?

haskell - 在 Haskell 中访问 "default show"?

arrays - 如何在 Julia 中为元组数组分配内存?

python - 在 python 中解析以分号分隔的文件以创建 CSV

haskell - 是否可以使用 Template Haskell 获得任何类型的表达式?

haskell - GHCi 中的奇怪行为

arrays - 为什么在Elixir中无法枚举元组?

c++ - 如何在 C++ 中将两个元组作为参数发送

python - 释放元组的元素?

haskell - 为什么 Prelude 中的 init 函数有两种定义?