3 ms·
And where do you find the inferred type signature?
by hristov 17y ago
And where do you find the inferred type signature?
- mbrubeck 17y agoI load the module into ghci and use the :t command. But I mostly do this during development. This is the big reason that production-quality code should generally have explicit type signatures for top-level functions.
- Periodic 17y agoIf we're talking about making code easy to read, type signatures are one of the best tools. Many times you can look at the name of a function and its arguments and you have a very good idea of what it does. This is unlike many dynamic languages where the returned value could be an object of just about any class. Are we getting a hash? An array? A custom class? Who knows without reading the details of the function.
- hristov 17y agoWell this kind of proves my point. If you have to compile code simply to read it, then the language is not very easy to read. What if you are reading the code in order to debug it and the code cant compile? And I know code should have type signatures but it often doesn't.
- jrockway 17y agoAnd I know code should have type signatures but it often doesn't. Often? All the libraries in GHC have type signatures. All the libraries on HackageDB I've used have type signatures. All the apps I've written have type signatures. Even most Haskell blog posts (and wiki pages) use type signatures. I think you should just peruse some production Haskell code, and try writing a bit of your own. If you set aside your belief that everyone is out to confuse you for a few minutes, I think you'll find that most Haskell is quite readable, and quite writable. You'll see how other people compose functions, what the idioms are, and then stuff like "sum = foldr1 (+)" won't confuse you anymore. Instead, I think you'll see how you can read and write code more quickly, and how to understand your program in terms of function application instead of in terms of passing around boxes that hold data.
- jrockway 17y agoPersonally, I write the type signature before I write the function implementing it. It is a nice thing to look at as you are writing the function; it keeps you focused on what to do. Oh, and it is great documentation, that the compiler ensures is up to date -- if your function does something the type signature disagrees with, your program won't compile. Excellent! One other thing I do, which is maybe not as common, is liberally using "type" aliases. Instead of: connectToDatabase :: String -> String -> String -> IO DatabaseHandle I would write: type Dsn = String type Username = String type Password = String connectToDatabase :: Dsn -> Username -> Password -> IO DatabaseHandle Self-documenting. (The type declarations also let you hang haddock documentation off them; good if you are using that type in more than one function. Then instead of documenting what a "Password" is everywhere you have a Password, you can just document it at the type declaration. Time-saving!) As an aside, I could also get type safety by using "newtype" instead of "type". For something this simple, though, I find the flexibility of being able to use any old String to be rather useful; ``connectToDatabase (mkDsn "MySQL:foobar") (mkUsername "jrockway") (mkPassword "OH HAI")'' is a bit verbose, after all. (I am also usually too lazy to derive Monad, MonadError, MonadWrite, and MonadIO instances for things like "type MyAction = ReaderT String (WriterT [String] (ErrorT String IO))", so I use type instead of newtype.)
- anamax 17y ago> Personally, I write the type signature before I write the function implementing it. It is a nice thing to look at as you are writing the function; it keeps you focused on what to do. Oh, and it is great documentation, that the compiler ensures is up to date -- if your function does something the type signature disagrees with, your program won't compile. Excellent! That partitions the function definition. And it's optional. And it could be somewhere else. And you get to argue with folks who like point-free because it's shorter.