Is a string value in Haskell a function?

From the instructions of the “Hello World” exercise of the Haskell track:

The objectives are simple:

  • Write a function that returns the string “Hello, World!”.
  • Run the test suite and make sure that it succeeds.
  • Submit your solution and check it at the website.

If everything goes well, you will be ready to fetch your first real exercise.

To complete this exercise, you need to implement the hello function.

You will find the type signature for hello already in place, but it is up to you to define the function.

(emphasis by me)

However, that given signature is hello :: String and indeed also the test expects a simple String value. Is such a value considered a function in Haskell? And if so, is the value’s type considered to be the return type of the function?

While I’m aware that functions are first-class values in Haskell, that doesn’t necessarily imply that every value is (considered) a function.

I’m further aware, that in pure lambda calculus, every representable value can be encoded as a function, but that’s just that—an encoding based on a choice of conventions (and only unambiguously decodable if that specific choice of conventions is known, as there are various possible ones), it doesn’t mean that a value actually is (nor is considered do be) the function used to represent it.

If all values are considered functions, the instructions should probably mention that. If values without -> in their type aren’t considered functions, either the exercise and corresponding test, or the wording of the instructions should be changed for them to be consistent with each other.

(As I don’t know which stance is the “correct” one, I didn’t open an issue or PR on GitHub - exercism/haskell: Exercism exercises in Haskell., yet.)

Trying to find an answer online, I found this Stack Overflow answer and, through it, The blog post “Everything is a function” in Haskell?, with some extensive discussion in the comments of the latter.

I don’t know how representative they are of the consensus within the Haskell community, but the gist seems to be: Although one can look at simple (non-->) values in Haskell as if they were (nullary) functions; strictly speaking, they aren’t functions.

1 Like

U-oh.

Those instructions are a holdover from adoption of this exercise from other tracks. The task is actually to define a constant hello :: String.

Strings are not functions, for functions are precisely the values with types of the form _ -> _.

It is safe to trust that blog post: it was written by Conal Elliott, who is plenty knowledgeable.

Very likely it is possible to devise a notion of function that applies to both _ -> _ and String, but I’m failing to find something that really works right now.

1 Like

Well, such a notion probably follows quite naturally from how Haskell emulates n-ary functions with currying and syntactic sugar:

type interpretation actually
a -> b -> c -> d 3-ary function function, whose return value has type b -> c -> d
a -> b -> c 2-ary function function, whose return value has type b -> c
a -> b 1-ary function function, whose return value has type b
a 0-ary function constant of type a

:upside_down_face:

This semblance can even be upheld with “normal” function definitions, but it breaks down with lambda-based ones:

type “normal” definition equivalent lambda-based definition
a -> b -> c -> d f x y z = … f = \ x y z -> …
a -> b -> c f x y = … f = \ x y -> …
a -> b f x = … f = \ x -> …
a f = … :grey_question: :person_shrugging:

Though one could simply drop the \ together with the last argument, which becomes somewhat more apparent when unsugared:

type “normal” definition equivalent lambda-based definition
a -> b -> c -> d f x y z = … f = \x -> \y -> \z -> …
a -> b -> c f x y = … f = \x -> \y -> …
a -> b f x = … f = \x -> …
a f = … f = …

But wait: Functions can be applied to values. Non-Function values cannot be applied to values. — But then again, currying (again! :sparkles:):

type value f can be …
a -> b -> c -> d … applied to 3 values: f x y z
a -> b -> c … applied to 2 values: f x y
a -> b … applied to 1 value: f x
a … “applied” to 0 values: f

Considering Freeing our maintainers, should I even bother to open an issue or pull request on GitHub?

Some tracks still accept pull requests, but from what I can see the Haskell track is auto-closing them.

I’d say to wait for a maintainer to weigh in on this discussion here before creating a PR, however it seems exercism/haskell only has 1 member and not sure they are active. I see some PRs by @MatthijsBlom so maybe he has more context.

This notion of function is equivalent to value, and therefore useless.

There is no syntactic sugar at play here. If you meant the equivalence of a -> (b -> c) and a -> b -> c: that’s just regular associativity, same as for ^, **, ^^, =<<, ….


I remembered just now that IO a values are often referred to as functions. Probably a cultural influence from outside. Although they don’t look like functions, in a sense they are.


Peter is not present on this forum. I and @ErikSchierboom are the closest you’re going to get, I guess.

I would welcome a PR on this, but I have no authority here.