You can't actually overload an existing non-typeclass function in Haskell.
What you can do is define a new function in a new type class, which is general enough to encompass both the original function and the new definition you want as an overload. You can give it the same name as the standard function, and avoid importing the standard one. That means in your module you can use the name !!
to get both the functionality of your new definition, and the original definition (the resolution will be directed by the types).
Example:
{-# LANGUAGE TypeFamilies #-}
import Prelude hiding ((!!))
import qualified Prelude
class Indexable a where
type Index a
type Elem a
(!!) :: a -> Index a -> Elem a
instance Indexable [a] where
type Index [a] = Int
type Elem [a] = a
(!!) = (Prelude.!!)
newtype MyType1 = MyType1 String
deriving Show
newtype MyType2 = MyType2 Int
deriving Show
newtype MyType3 = MyType3 Char
deriving Show
instance Indexable MyType1 where
type Index MyType1 = MyType2
type Elem MyType1 = MyType3
MyType1 cs !! MyType2 i = MyType3 $ cs !! i
(I've used type families to imply that for a given type that can be indexed, the type of the indices and the type of the elements automatically follows; this could of course be done differently, but going into that in more detail is getting side-tracked from the overload question)
Then:
*Main> :t (!!)
(!!) :: Indexable a => a -> Index a -> Elem a
*Main> :t ([] !!)
([] !!) :: Int -> a
*Main> :t (MyType1 "" !!)
(MyType1 "" !!) :: MyType2 -> MyType3
*Main> [0, 1, 2, 3, 4] !! 2
2
*Main> MyType1 "abcdefg" !! MyType2 3
MyType3 'd'
It should be emphasised that this has done absolutely nothing to the existing !!
function defined in the prelude, nor to any other module that uses it. The !!
defined here is a new and entirely unrelated function, which just happens to have the same name and to delegate to Prelude.!!
in one particular instance. No existing code will be able to start using !!
on MyType1
without modification (though other modules you can change can of course import your new !!
to get this functionality). Any code that imports this module will either have to module-qualify all uses of !!
or else use the same import Prelude hiding ((!!))
line to hide the original one.
(!!)
and having at least one qualified, or by using(!)
for lookup/indexing. You can't really overload arbitrary functions/operators in Haskell. – kqr!!
, if by overload you mean ad-hoc non-typeclass-based polymorphism. You can "overload" it the same way you "overload"fmap
,<$>
, or>>=
, but they must be restricted to an explicit typeclass (like monad or applicative, or "list-like") and their type signature be generalized to the entire typeclass. Your best bet would be to define the type signature of your own new, generalized(!!)
for a typeclass, and define instances for everything you will want to ever(!!)
. – Justin L.