The philosophy of these changes is here. Summary of changes is:
- Application must be explicitly shown with a dot (Dijkstra philosophy)
- This applies to other non first class applications as well
viz. type constructors (
Tree.a
) and class constructors (Eq.a
) -
bind
is reversed and called with a double dot..
(so that the generalization of simple application to monadic bind is apparent) - syntax of data is changed to
ctype
− concrete type − so that the syntax es (is it syntices?) ofclass
,instance
andctype
are uniform[1]. - : and :: are flipped
To allow for the above changes the following changes are also there enumFrom
etc use triple dot instead of double dot- composition is named '
;
' and is in left-to right order
And to make allowances for the above - layout is the only way to denote nesting. Use of {} gives the error
Layout imperative in functional programming
.
The modified prelude should give an idea of how it looks.
The original gofer – a wonderful work of art by Mark Jones – is Mark Jones archive.
There is still some interest and use in pugofer (after 22 years!) and it compiles on modern systems. I can provide more tips to anyone who is interested. Some people find a pedagogical advantage to using a system that is a hundredfold smaller than ghc. As long as you are not looking for 'realistic' and/or 'modern' :-)
Specifically it can be useful if the agenda is – Think in haskell; code in Java/C++.
[A recent training request was from a team using javascript]
A big plus is that if one uses the simple prelude there are no type-classes/overloaded values, thus making the essence of Hindley-Milner much more easy to grasp.
For those wanting to write (real) code in haskell please use ghc!! For those wanting a 'why' as to pedagogic superiority of gofer over ghc, here's the error they give for 1 ++ [2,3,4]
- Gofer
? 1 ++ [2,3,4] ERROR: Type error in application *** expression : 1 ++ [2,3,4] *** term : 1 *** type : Int *** does not match : [Int]
- Ghc
Prelude> 1 ++ [2,3,4]
:2:1: No instance for (Num [a0]) arising from the literal `1' Possible fix: add an instance declaration for (Num [a0]) In the first argument of `(++)', namely `1' In the expression: 1 ++ [2, 3, 4] In an equation for `it': it = 1 ++ [2, 3, 4] :2:7: No instance for (Num a0) arising from the literal `2' The type variable `a0' is ambiguous Possible fix: add a type signature that fixes these type variable(s) Note: there are several potential instances: instance Num Double -- Defined in `GHC.Float' instance Num Float -- Defined in `GHC.Float' instance Integral a => Num (GHC.Real.Ratio a) -- Defined in `GHC.Real' ...plus three others In the expression: 2 In the second argument of `(++)', namely `[2, 3, 4]' In the expression: 1 ++ [2, 3, 4]
- Standard Prelude
? :t (==) (==) : Eq.a => a -> a -> Bool ? :t (+) (+) : Num.a => a -> a -> a
- Simple Prelude
? :t (==) (==) : a -> a -> Bool ? :t (+) (+) : Int -> Int -> Int ?
Eq.a => a -> a -> Bool
to
a -> a -> Bool
would solve the halting-problem! Right... I am not talking theory; just teaching kids
[1] Nowadays called GADTs. This was 10+ years before. Same syntax different intention.
Having suffered cabal hell with my students during the Autumn term last year, I feel very drawn to this idea...
ReplyDeletePS - the links above to standard and simple prelude have gone stale - I get github's 404 webpage for them.
Links corrected -- please check.
DeleteAnd if you do try do keep me posted!
[When you build ie make there are some compile errors...
its only for gofc -- the compiler -- the interpreter gofer should be ok