1

I'm super bloody new to Haskell. Coming from other languages like Java or C I have some problems understanding how functions in Haskell use arguments. I understand the concept of polymorphism, how Haskell uses types and how everything seems to be a tree but I have a hard time applying these concepts to the syntax.

Let's say I want to program a function that takes a string-list and just adds "1" and "2" to it.

addOneTwo :: [String] -> [String]
addOneTwo [] = "1" : "2" : [x]

I understand that this question might have been answered elsewhere but I have not yet seen an answer that explains it in a way so that I as a total newbi can understand.

2
  • 1
    What exactly is your question? Commented Nov 2, 2022 at 23:11
  • f [] = ... means "if the input list is empty then the result is ...". Usually it's followed by another equation covering the non-empty case. I don't know why you use that in your code. Try instead f xs = "1" : "2" : xs -- no need to distinguish between the empty/nonempty cases here. Commented Nov 2, 2022 at 23:18

1 Answer 1

2
addOneTwo :: [String] -> [String]
addOneTwo [] = "1" : "2" : [x]

This says:

  • addOneTwo is a function that accepts a [String] and returns a [String]

  • When addOneTwo is called on an empty list, that is, addOneTwo [], it evaluates to a list where:

    • The head is "1"
    • The tail is a list where:
      • The head is "2"
      • The tail is a list of one element, x (or, in other words, its head is x and its tail is [])

Since you don’t define a variable called x in this code, this is a scoping error. One way to fix this is the following:

  • Remove the pattern [] and replace it with the pattern x, that is, just a parameter name.

  • Since this parameter is a list, use it as the second operand of the cons operator (:) directly, that is, … : x instead of *… : [x]

addOneTwo :: [String] -> [String]
addOneTwo x = "1" : "2" : x

Conventionally, lists are often named with an s suffix, like xs or strings, so you could rename x too if you like.

To understand your original code in more depth, maybe it’ll be illuminating to go over how it would be desugared:

addOneTwo =
  \ xs -> case xs of {
    [] -> "1" : ("2" : (x : []));
    _ -> error "Non-exhaustive patterns in function addOneTwo"
  }

Since addOneTwo is a function, it can be defined using a function value, that is, a lambda expression. I’ve given the parameter of this function the name of xs. When you write the definition addOneTwo [] = …, the pattern addOneTwo [] means you’re defining the result of evaluating the expression addOneTwo []. The “equals” sign really does mean “equals”!

This is equivalent to taking a parameter and pattern-matching on it explicitly with a case expression. Notice that I included an error case, which is implicitly generated when you don’t cover all possible inputs—in this case, when addOneTwo is applied to a non-empty list, like addOneTwo [3]. GHC can warn you about such uncovered cases if you enable -Wincomplete-patterns; that’s implied by -Wall, which produces a variety of other helpful warnings.

Whereas, the corrected definition would desugar to the following:

addOneTwo =
  \ x ->
    "1" : ("2" : x)

Since all inputs will be matched by the pattern x, there is no need for an error alternative, or any case expression at all.

I want to program a function that takes a string-list and just adds "1" and "2" to it.

Well, there you go! But keep in mind: this isn’t adding elements to the same list in-place, it’s just making a list that shares some suffix with the old one. And that’s the normal way of representing incremental updates to a data structure in Haskell: a function f :: T -> T takes in a value representing one state and returns a value representing the modified state, and we rely on the garbage collector to reclaim parts of the old state that are no longer used.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.