使用下面的函数查找元组中的第 n 个元素

Bea*_*row 6 haskell tuples

“使用以下带有两个参数的函数:

nth :: (a,a,a,a,a) -> Int -> a
Run Code Online (Sandbox Code Playgroud)

其中 Int 值应返回五元素元组的第 Int 值。”我尝试过:

nth (a,b,c,d,e) x = (a,b,c,d,e) !! x
Run Code Online (Sandbox Code Playgroud)

但 GHC 给了我一条错误消息:

file.hs:11:21: error:
* Couldn't match expected type `[a1]'
              with actual type `(a, b, c, d, e)'
* In the first argument of `(!!)', namely `(a, b, c, d, e)'
  In the expression: (a, b, c, d, e) !! x
  In an equation for `nth':
      nth (a, b, c, d, e) x = (a, b, c, d, e) !! x
* Relevant bindings include
    e :: e (bound at file.hs:11:14)
    d :: d (bound at file.hs:11:12)
    c :: c (bound at file.hs:11:10)
    b :: b (bound at file.hs:11:8)
    a :: a (bound at file.hs:11:6)
    nth :: (a, b, c, d, e) -> Int -> a1
      (bound at file.hs:11:1)
Run Code Online (Sandbox Code Playgroud)

我应该怎么办?我应该如何写这个方程的元组部分?感谢您提前的答复!

Wil*_*sem 6

您不能使用(!!) :: [a] -> Int -> a,因为正如签名所示,它适用于列表,而不是元组。您可以使用模式匹配并将其实现为:

nth :: (a, a, a, a, a) -> Int -> a
nth (a, _, _, _, _) 0 = a
nth (_, b, _, _, _) 1 = b
nth (_, _, c, _, _) 2 = c
nth (_, _, _, d, _) 3 = d
nth (_, _, _, _, e) 4 = e
Run Code Online (Sandbox Code Playgroud)

已经有人提出将 3 元组定义为(a, (b, c))递归结构,其中n 元组被定义为2元组,其中n-1 元组作为第二项。但事实并非如此(目前)。


ama*_*loy 5

您可以通过将元组的模式匹配与 上的匹配分开来避免现有模式匹配解决方案中的一些重复n

nth :: (a, a, a, a, a) -> Int -> a
nth (a, b, c, d, e) n = case n of
  0 -> a
  1 -> b
  2 -> c
  3 -> d
  4 -> e
Run Code Online (Sandbox Code Playgroud)

您还应该考虑当 n 不在范围内时想要发生什么[0, 4]。正如所写的,您将在运行时得到一个非详尽的模式错误。更诚实的是返回 aMaybe a或采用更受约束的类型作为输入,例如

data QuintupleIndex = Zero | One | Two | Three | Four
Run Code Online (Sandbox Code Playgroud)