一行中多个函数调用的语法 - Haskell

时间:2014-04-18 00:06:59

标签: haskell

这可能非常简单,但我是Haskell的新手,并且不知道我在做什么。

我有三个功能:

first :: (Int, [Char], [[Char]], [((Int,Int),(Int,Int))]) -> (Int, [Char], [[Char]])
first (a, arr, stringlist, []) = (a, arr, stringlist)
first (a, arr, stringlist, (x:xs))
    | snd(snd(x)) == 1 = (first $ (second (a, arr, stringlist)) xs)
    | otherwise = (first $ (third (a arr stringlist x)) xs)

second :: (Int, [Char], [[Char]]) -> (Int, [Char], [[Char]])

third :: (Int, [Char], [[Char]], ((Int,Int),(Int,Int))) -> (Int, [Char], [[Char]])

第二个和第三个都有效,所以这些细节无关紧要。 我确信在我的第一个实现中有多个错误,但是那个部分是

(first $ (second (a, arr, stringlist)) xs)

是我的主要问题。调用秒然后将结果和列表的尾部传递给第一个的正确方法是什么?

1 个答案:

答案 0 :(得分:3)

您绝对应该考虑某些类型的别名,或者更好地使用record syntax来简化您的类型签名。你也可以摆脱很多这些括号:

first :: (Int, [Char], [[Char]], [((Int,Int),(Int,Int))]) -> (Int, [Char], [[Char]])
first (a, arr, stringlist, []) = (a, arr, stringlist)
first (a, arr, stringlist, (x:xs))
    | snd (snd x) == 1 = first $ (second (a, arr, stringlist)) xs
    | otherwise = first $ (third $ a arr stringlist x) xs

我认为这样可以更容易地看到您的语法有点错误。你所拥有的是将参数xs传递给second (a, arr, stringlist),它不会返回一个函数,因此会导致错误,类似于第二种情况。如果你把它改成了,那就更接近正确了。

first :: (Int, [Char], [[Char]], [((Int,Int),(Int,Int))]) -> (Int, [Char], [[Char]])
first (a, arr, stringlist, []) = (a, arr, stringlist)
first (a, arr, stringlist, (x:xs))
    | snd (snd x) == 1 = first (second (a, arr, stringlist)) xs
    | otherwise = first (third $ a arr stringlist x) xs

我也看到你将4个参数传递给third,当它应该采用4元组时,所以可能会像

一样
first :: (Int, [Char], [[Char]], [((Int,Int),(Int,Int))]) -> (Int, [Char], [[Char]])
first (a, arr, stringlist, []) = (a, arr, stringlist)
first (a, arr, stringlist, (x:xs))
    | snd (snd x) == 1 = first (second (a, arr, stringlist)) xs
    | otherwise = first (third (a, arr, stringlist, x)) xs

现在我们遇到的问题是,当你只想要一个参数时,你将两个参数传递给first。你有(Int, [Char], [[Char]])类型和[((Int, Int), (Int, Int))]类型的东西,你想把它们组合成一个4元组。我建议做一个辅助功能来做到这一点:

mk4from3 :: (a, b, c) -> d -> (a, b, c, d)
mk4from3 (a, b, c) d = (a, b, c, d)

然后你可以简单地写

first :: (Int, [Char], [[Char]], [((Int,Int),(Int,Int))]) -> (Int, [Char], [[Char]])
first (a, arr, stringlist, []) = (a, arr, stringlist)
first (a, arr, stringlist, (x:xs))
    | snd (snd x) == 1 = first $ mk4from3 (second (a, arr, stringlist)) xs
    | otherwise = first $ mk4from3 (third (a, arr, stringlist, x)) xs

我在决定是否应该将元组转换为自己的数据类型时使用的一般经验法则是,如果我在多个类型签名中使用3元组或更大元组,我应该将其作为数据类型,即使它不使用记录语法,而只是使用ADT功能。