Starting point:
fn :: [a] -> Int
fn = (2 *) . length
Let\'s say we only want to constrain the return value, then we could write:
To specify only the type of an argument, you can write something like
fn list = 2 * length list
where
a :: [Char]
a = list `asTypeOf` a
So that it is easy to later amend it like, e.g.,
fn list = 2 * fromIntegral (length list)
where
a :: [Char]
a = list `asTypeOf` a
and have its inferred type change accordingly:
*Main> :t fn
fn :: [Char] -> Int
*Main> :r
-- changed file reloaded
*Main> :t fn
fn :: (Num t) => [Char] -> t
You could use the same contorted technique to specify the return type of a function, perhaps defined in pointfree style, but this is not pretty.
fn2 list = r
where
r :: Int
r = f list
f = (2 *) . length
It is also not much different from what you have right now, just keeps the code and the type spec separated.