I\'m new to Haskell and would like to know whether it\'s possible to define a function that is only defined on a subset of an already existing type, without actually having
No. The type system would need to support refinement types (or full dependent types, as suggested by @jozefg).
Here is a Haskell extension with refinement types.
http://goto.ucsd.edu/~rjhala/liquid/haskell/blog/blog/2013/01/01/refinement-types-101.lhs/
One possibility would be
newtype Even n = Even n
getEven (Even n) = 2*n
squared :: Num n => Even n -> Even n
squared (Even n) = Even (2*n*n)
In general no. Such a thing is called a subset type, it's a hallmark of dependent types which Haskell doesn't have. Usually it's implemented by boxing a value with a proof that the value satisfies some property, but since we have no notion of proofs in Haskell, we're stuck.
Usually the way to fake it is with "smart constructors".
newtype Even = Even {unEven :: Integer} deriving (Eq, Show, Ord)
toEven :: Integer -> Maybe Even
toEven a | even a = Just $ Even a
| otherwise = Nothing
And then hide the Even
constructor.
If you really really want it, you can switch to a language that can interop with Haskell that has dependent types (Coq and Agda spring to mind).
Wrap the subset in a newtype
newtype EvenInteger = EvenInteger {
unEvenInteger :: Integer
} deriving (Show, Eq, Ord, Num)
mkEvenInteger :: Integer -> Maybe EvenInteger
mkEvenInteger n = case n % 2 of
0 -> Just $ EvenInteger n
_ -> Nothing
squared :: EvenInteger -> EvenInteger
squared n = n * n
As mentioned elsewhere, refinement types like in LiquidHaskell can express this. Here's what it looks like:
module Evens where
{-@ type Even = {v:Int | v mod 2 = 0} @-}
{-@ square :: Even -> Int @-}
square :: Int -> Int
square n = n * n
-- calling the function:
yup = square 4
-- nope = square 3 -- will not compile if this is uncommented
You can try this out by plugging it in here: http://goto.ucsd.edu:8090/index.html