In some languages, overloading means using the same name for several functions that provide similar but different functionality, so you might try
split :: String -> [String] -- splits on whitespace
split :: Char -> String -> [String] -- splits on the given character
split :: [Char] -> String -> [String] -- splits on any of the given characters
split :: (Char -> Bool) -> String -> [String] -- splits using a function that tells you when
which would give you the Duplicate type signature
error you're getting.
Haskell doesn't do this type of overloading, and a Haskell programmer would give these different names:
words :: String -> [String] -- splits on whitespace
splitOn :: Char -> String -> [String] -- splits on the given character
splitsOn :: [Char] -> String -> [String] -- splits on any of the given characters
splitWith :: (Char -> Bool) -> String -> [String] -- splits using a function that tells you when
The reason that Haskell doesn't allow the kind of overloading I think you're asking about, is that it genuinely doesn't let you do anything that you couldn't do without it, and allowing it would make it almost impossible to do more advanced sorts of overloading. Haskell's overloading is a very powerful tool indeed; find out about type classes and constructor classes to get started.
Actually, since String
= [Char]
, and Haskell programmers love code reuse, they'd be far more likely to write:
words :: String -> [String]
splitOn :: Eq a => a -> [a] -> [[a]]
splitsOn :: Eq a => [a] -> [a] -> [[a]]
splitWith :: (a -> Bool) -> [a] -> [[a]]
Here Eq a
is an example of a kind of overloading Haskell does allow, where splitOn
will let you split any list as long as the items can be compared for equality (i.e. Haskell lets you define your own notion of equality). You can use this then to split a String, or for example a list of Strings, but you can't split a list of functions because you can't check two functions to see if they're equal. splitWith
is an example of Haskell letting you treat a function just like most other data - you can pass one as an argument!
[Note 1: words
is a standard function, splitWith
is in a library with a slightly different typesignature.]
[Note 2: if you wanted to actually write these functions, here's how:
splitWith isSplitter list = case dropWhile isSplitter list of
[] -> []
thisbit -> firstchunk : splitWith isSplitter therest
where (firstchunk, therest) = break isSplitter thisbit
-- words = splitWith isSpace -- not needed, standard function from the Prelude
splitOn c = splitWith (== c) -- notice I passed == in an argument!
splitsOn chars = splitWith (`elem` chars)
]