Hier die Zusammenfassung zum Thema Typklassen (Erster Teil von Kapitel 6 von Real World Haskell). Konkret folgende Unterkapitel:
String
data Color = Red | Green | Blue
colorEq :: Color -> Color -> Bool
colorEq Red Red = True
colorEq Green Green = True
colorEq Blue Blue = True
colorEq _ _ = False
stringEq :: [Char] -> [Char] -> Bool
stringEq [] [] = True
stringEq (x:xs) (y:ys) = x == y && stringEq xs ys
stringEq _ _ = False
colorEq :: Color -> Color -> Bool
stringEq :: [Char] -> [Char] -> Bool
/=
müssen mehrfach implementiert werdenclass
Syntax zur Definition der Typklasse:
class BasicEq a where
isEqual :: a -> a -> Bool
ghci> :type isEqual
isEqual :: (BasicEq a) => a -> a -> Bool
Syntax zur Implementierung von Instanzen (bisher nur Bool
):
instance BasicEq Bool where
isEqual True True = True
isEqual False False = True
isEqual _ _ = False
ghci> isEqual False False
True
ghci> isEqual False True
False
Weitere Funktion für die Typklasse:
class BasicEq2 a where
isEqual2 :: a -> a -> Bool
isNotEqual2 :: a -> a -> Bool
isNotEqual
kann man von isEqual
ableitenclass BasicEq3 a where
isEqual3 :: a -> a -> Bool
isEqual3 x y = not (isNotEqual3 x y)
isNotEqual3 :: a -> a -> Bool
isNotEqual3 x y = not (isEqual3 x y)
Eq
verlangt, dass man eine Funktion implementiertStatt ...
colorEq Red Red = True
colorEq Green Green = True
colorEq Blue Blue = True
colorEq _ _ = False
Color
in die Typklasse BasicEq3
aufnehmeninstance
isEqual3
instance BasicEq3 Color where
isEqual3 Red Red = True
isEqual3 Green Green = True
isEqual3 Blue Blue = True
isEqual3 _ _ = False
String
s umshow :: (Show a) => a -> String
ghci> show [1, 2, 3]
"[1,2,3]"
ghci> show "Hello!"
"\"Hello!\""
ghci> putStrLn (show "Hello!")
"Hello!"
Instanz von Show
implementieren:
data Color = Red | Green | Blue
instance Show Color where
show Red = "Red"
show Green = "Green"
show Blue = "Blue"
Show
read :: (Read a) => String -> a
main = do
putStrLn "Please enter a Double:"
inpStr <- getLine
let inpDouble = (read inpStr)::Double
putStrLn ("Twice " ++ show inpDouble ++ " is " ++ show (inpDouble * 2))
Bei Mehrdeutigkeiten sind Typannotationen nötig:
ghci> read "5"
<interactive>:1:0:
Ambiguous type variable `a' in the constraint:
`Read a' arising from a use of `read' at <interactive>:1:0-7
Probable fix: add a type signature that fixes these type variable(s)
ghci> :type (read "5")
(read "5") :: (Read a) => a
ghci> (read "5")::Integer
5
ghci> (read "5")::Double
5.0
ghci> (read "5.0")::Double
5.0
ghci> (read "5.0")::Integer
*** Exception: Prelude.read: no parse
Implementierung von Read
für Color
:
instance Read Color where
-- readsPrec is the main function for parsing input
readsPrec _ value =
-- We pass tryParse a list of pairs. Each pair has a string
-- and the desired return value. tryParse will try to match
-- the input to one of these strings.
tryParse [("Red", Red), ("Green", Green), ("Blue", Blue)]
where tryParse [] = [] -- If there is nothing left to try, fail
tryParse ((attempt, result):xs) =
-- Compare the start of the string to be parsed to the
-- text we are looking for.
if (take (length attempt) value) == attempt
-- If we have a match, return the result and the
-- remaining input
then [(result, drop (length attempt) value)]
-- If we don't have a match, try the next pair
-- in the list of attempts.
else tryParse xs
ghci> (read "Red")::Color
Red
ghci> (read "Green")::Color
Green
ghci> (read "Blue")::Color
Blue
ghci> (read "[Red]")::[Color]
[Red]
ghci> (read "[Red,Red,Blue]")::[Color]
[Red,Red,Blue]
ghci> (read "[Red, Red, Blue]")::[Color]
*** Exception: Prelude.read: no parse
Parsec
ghci> let d1 = [Just 5, Nothing, Nothing, Just 8, Just 9]::[Maybe Int]
ghci> putStrLn (show d1)
[Just 5,Nothing,Nothing,Just 8,Just 9]
ghci> writeFile "test" (show d1)
ghci> input <- readFile "test"
"[Just 5,Nothing,Nothing,Just 8,Just 9]"
ghci> let d2 = (read input)::[Maybe Int]
ghci> print d1
[Just 5,Nothing,Nothing,Just 8,Just 9]
ghci> print d2
[Just 5,Nothing,Nothing,Just 8,Just 9]
ghci> d1 == d2
True
Show
und Read
müssen "zusammenpassen"Show
und Read
implementierenclass Num a where
(+) :: a -> a -> a
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
Num
Num
verwendenTable 6.1. Selected Numeric Types
[...]
Source von Eq
(Ausschnitt):
infix 4 ==, /=
-- | The 'Eq' class defines equality ('==') and inequality ('/=').
-- All the basic datatypes exported by the "Prelude" are instances of 'Eq',
-- and 'Eq' may be derived for any datatype whose constituents are also
-- instances of 'Eq'.
--
-- Minimal complete definition: either '==' or '/='.
--
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
x == y = not (x /= y)
Definition von Ord
:
data Ordering = LT | EQ | GT
-- Minimal complete definition: compare or (<=)
class Eq a => Ord a where
compare :: a -> a -> Ordering
(<) :: a -> a -> Bool
(>=) :: a -> a -> Bool
(>) :: a -> a -> Bool
(<=) :: a -> a -> Bool
max :: a -> a -> a
min :: a -> a -> a
Ord
baut auf Eq
aufData.List.sort