The problem is now that I have a growing codebase, as soon as I change one thing, my code breaks all over the place and I am consumed with tracking down all of the problems.
This is actually advertised as a feature in Yesod (a Haskell web framework). Suppose I have specified the following routing specification:
/blog/#String BlogR GET
And I decide I want to change it to
/blog/#Date/#String BlogR GET
As soon as I make this change to the routes, the compiler will tell me everywhere that I have broken my code. I will be forced to update the getBlogR
function - changing its input type so it also accepts a Date
. I will also be forced to update any place where I use type safe URLs in my templates, which would look something like @{BlogR (slug p)}
-> @{BlogR (date p) (slug p)}
.
This is considered a Good Thing, because the type checker is helping you to find problems introduced by the changes you made.
Now, regarding ghci.
ghci> let shew = show
ghci> :t shew
shew :: () -> String
ghci> :t show
show :: Show a => a -> String
It is sometimes true that ghci chooses annoying defaults. This, however, can be alleviated.
ghci> :set -XNoMonomorphismRestriction
ghci> let shew = show
ghci> :t shew
shew :: Show a => a -> String
While using ghci to discover the type of a function is great for beginners, I wouldn't recommend relying on ghci. Learn what the type signatures mean, and how to discover them yourself. In fact, start writing a function by first writing the type signature you intend it to have. It only takes a small investment of time to learn this skill, and it is a great boon to programming when you can use Haskell's type system to your advantage.