Colon Scope
Lets talk a little bit about declaring functions.
rx :: [a] -> a -> [a]
rx [] r = [r]
rx (x:xs) r = x : rx xs r
It is not entirely obvious what the various bits are, so let’s use some long names to make it more readable.
myInfix :: [something] -> something -> [something]
myInfix [] atEnd = [ atEnd ]
myInfix (listHead:listTail) atEnd = listHead : ( myInfix listTail atEnd )
Something magical and weird is happening at the double colon :: We are declaring the type for our method myInfix. If this were another language, we would think about the type declaration as: My Function takes a List and an Element, then produces another List. If that were the case, we would expect to see the following:
- myInfix :: ( [something] , something) -> [something]
But that conception is false. Instead, we are saying: My Function takes a List, then produces another (invisible) Function which takes an Element, which in turn produces a List. So we can conceptually group that as follows:
- ( (myInfix :: [something]) -> something ) -> [something] – but do not actually group this way, as it won’t compile
Next to consider :: ’something‘ is not an actual type. Instead it represents any type that we decide to use with the function. The fact that ‘something‘ is mentioned in three places does create a constraint. We must use and expect the same type in each of the three places. So the following examples work:
- myInfix [1,2] 6 produces [1,2,6]
- myInfix “hi” ‘o’ produces “hio”
But the following fail:
- myInfix [1,2] ‘n’
- myInfix[False,True] 8


