简体   繁体   中英

Syntax for multiple function calls in one line - Haskell

This may be really straightforward but I'm new to Haskell and have no idea what I'm doing.

I have three functions:

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]])

Second and third both work so the details of those don't matter. I'm sure there are multiple errors in my implementation of first but the part that says

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

is my main issue. What is the proper way to call second and then pass the result and the tail of the list to first?

You should definitely consider some type aliases, or even better use record syntax to simplify your type signatures. You can also get rid of a lot of those parentheses:

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

And I think this makes it easier to see that your syntax is a bit wrong. What you have is passing the argument xs to second (a, arr, stringlist) , which does not return a function so it will result in an error, and similarly with the second case. If you changed it to this, it would be closer to correct.

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

I also see that you're passing 4 arguments to third , when it should be taking a 4-tuple, so maybe something like

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

Now we get to the problem that you're passing two arguments to first when you only want one argument. You have something of type (Int, [Char], [[Char]]) and something else of type [((Int, Int), (Int, Int))] , and you want to combine them into a 4-tuple. I would suggest making an auxiliary function to do just that:

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

Then you can simply write

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

The general rule of thumb I use when deciding if I should convert a tuple into its own data type is if I use a 3-tuple or larger in more than one type signature, I should make it a data type, even if it isn't using record syntax and instead just uses ADT features.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM