如何修改元组的值,然后将它们作为元组的元组返回?

mab*_*bub 5 haskell functional-programming

总的来说,我对编程和 Haskell 还比较陌生。我正在读一本关于该语言的书,其中一个练习要求以下内容:

fst使用和填写以下函数的定义snd

f :: (a, b) -> (c, d) -> ((b, d), (a, c))
f = undefined
Run Code Online (Sandbox Code Playgroud)

我很困惑这个函数签名对于如何定义实际函数以及该定义中的操作顺序意味着什么。用通俗的语言来说,这就是“取一个元组,另一个元组,然后输出最终的混合元组”吗?或者它是在说“获取一个元组,修改该元组,然后将修改后的元组与原始元组混合”?

我的问题是,如何编写函数定义,以便fstsnd可以生成新元组?我知道我不应该使用很多括号,但在我看来,我想通过仅使用括号创建一个单行函数来简单地划分操作顺序来解决问题,例如:

f x y = (,) ((,) snd x snd y) ((,) fst x fst y)
Run Code Online (Sandbox Code Playgroud)

但编译器返回错误。我是否把这件事过于复杂化了?x和分别y绑定到(a,b)(c,d),所以我不应该能够访问它们并返回一个元组的新元组,其顺序与我用括号进行的操作顺序相同吗?

Wil*_*sem 8

我是否把这件事过于复杂化了?

可能是的,最直接的方法可能是简单地进行模式匹配,例如:

f :: (a, b) -> (c, d) -> ((b, d), (a, c))
f (a, b) (c, d) = ((b, d), (a, c))
Run Code Online (Sandbox Code Playgroud)

虽然它不是一个“聪明的技巧”或什么的,但它是可读的,并且易于检查、调试和修复。

至于实现,您可以通过以下方式解决此问题:

f x y = (,) ((,) (snd x) (snd y)) ((,) (fst x) (fst y))
Run Code Online (Sandbox Code Playgroud)

或者通过以下方式使这更方便:

f x y = ((snd x, snd y), (fst x, fst y))
Run Code Online (Sandbox Code Playgroud)

但是,如果定义模式意味着您要引入 lambda 表达式,那么使用fstand通常很有用。snd如果您可以定义模式,通过使用元组模式可以使其更具可读性。

对于你的函数来说,只有一个有意义的实现(除了undefined在某个地方使用(子)表达式之外),Djinn是一个可以(详尽地)枚举简单类型的实现的工具,这是 Djinn 可以找到的唯一一个。