4

I noticed that this is not legal in Haskell:

foo :: [a] -> [a]
foo [] = []

bar = 3

foo (x:xs) = x : foo xs

However, this is:

foo :: [a] -> [a]

bar = 3

foo [] = []
foo (x:xs) = x : foo xs

Though the patterns matched for a function must all be grouped together as a set, it seems the type signature can wander. But how far? I was told it must be in the same "block"... but technically speaking, what exactly is a "block"?

1 Answers1

5

The declarations for each function must be together, other than that declarations can occur in files in any order.

The declarations section of the Haskell report, in section 4.4.3.1 Functions Bindings, says

Note that all clauses defining a function must be contiguous, and the number of patterns in each clause must be the same. The set of patterns corresponding to each match must be linear---no variable is allowed to appear more than once in the entire set.

You have four top-level declarations:

A declaration for bar

bar = 3

Two declarations for foo

foo [] = []
foo (x:xs) = x : foo xs

A type signature for foo

foo :: [a] -> [a]

Except for the contiguous declarations for function bindings, these can be in any order any distance from each other in the same file and still have the same meaning.

let and where

let and where also introduce non-top-level declarations. In these declaration scopes, except for the contiguous declarations for functions, declarations can occur in any order and still have the same meaning. Declarations made in different scopes do not necessarily have the same meaning. Scopes are described in the expressions sections of the Haskell report, in section 3.12 Let Expressions

Let expressions have the general form let { d1 ; ... ; dn } in e, and introduce a nested, lexically-scoped, mutually-recursive list of declarations (let is often called letrec in other languages). The scope of the declarations is the expression e and the right hand side of the declarations. Declarations are described in Chapter 4.

Besides function bindings and pattern bindings, a let or where can also introduce type signatures and fixity declarations.

Cirdec
  • 24,019
  • 2
  • 50
  • 100
  • See [comment here](http://stackoverflow.com/questions/24977706/any-way-to-add-patterns-type-signature-to-a-function-in-ghci#comment38829825_24977726) that inspired the question. "File" granularity can't be the whole story... (?) – HostileFork says dont trust SE Jul 27 '14 at 07:14
  • I added a section about the scopes introduced by let and where. – Cirdec Jul 27 '14 at 07:19