Differences
This shows you the differences between two versions of the page.
Both sides previous revision Previous revision Next revision | Previous revision | ||
pp:class [2021/04/10 16:18] lfa |
pp:class [2021/04/11 22:15] (current) lfa |
||
---|---|---|---|
Line 1: | Line 1: | ||
====== 6. Classes in Haskell ====== | ====== 6. Classes in Haskell ====== | ||
+ | |||
+ | === Default Classes === | ||
+ | |||
+ | Today you can use the provided {{:pp:lab6_skel.zip|}}. | ||
Last time we've learned how to define our new data types in Haskell. The simpler ones were ''Ordering'' (some "constants"), ''Point Float Float'', and ''Student String String [Float]''. | Last time we've learned how to define our new data types in Haskell. The simpler ones were ''Ordering'' (some "constants"), ''Point Float Float'', and ''Student String String [Float]''. | ||
- | We've seen that we can define recursively monomorphic or polymorphic types, like ''List a'' and ''BTree a''. | + | We've seen that we can define //recursively// //monomorphic// or //polymorphic// types, like ''List a'' and ''BTree a''. |
- | Today we will use the following data: | + | Today we will use the following data types: |
<code haskell> | <code haskell> | ||
data List a = Null | Cons a (List a) | data List a = Null | Cons a (List a) | ||
Line 22: | Line 26: | ||
Now let's check one more interesting concept, Haskell's class system. | Now let's check one more interesting concept, Haskell's class system. | ||
- | If //data// can be considered the //class// from Java, then ''class'' could be considered the //interface// from Java. | ||
If you're defining a new //data Point//, you probably encountered some problems trying to print it in GHCI. | If you're defining a new //data Point//, you probably encountered some problems trying to print it in GHCI. | ||
Line 33: | Line 36: | ||
show :: a -> String | show :: a -> String | ||
</code> | </code> | ||
- | Here ''a'' is a **data**. More precisely, to be able to print any data from Haskell, then it must implement the //show// function. That's why we can consider it an //interface//. | + | Here ''a'' is a **data type**. More precisely, to be able to print any data type from Haskell, then it must implement the //show// function. That's why we can consider it an //interface//. |
Providing our show will be done by enrolling our type in the already existing class Show. Here you have a simple example, in the lab skel you'll see a more complex show, //just for flexing//. | Providing our show will be done by enrolling our type in the already existing class Show. Here you have a simple example, in the lab skel you'll see a more complex show, //just for flexing//. | ||
Line 44: | Line 47: | ||
1. Add List and Student to the Show class. You can print them however you want. If you aren't inspired today, you can use the following: | 1. Add List and Student to the Show class. You can print them however you want. If you aren't inspired today, you can use the following: | ||
- | * The lists can be the default style -> //[3,4,1,2,]//. | + | * The lists can be the default style -> //[3,4,1,2,]// |
- | * The student can be something like -> //Studentul: ANDREI Alex-Bogdan = [8.5,6.0,8.7]// | + | * The student can be something like -> //Studentul: ANDREI Alex-Bogdan = [8.5,6.0,8.7]// |
2. The default ''=='' that we get from //deriving Eq// will check if 2 objects are identical. For our data, you'll have to provide a custom '==' such that: | 2. The default ''=='' that we get from //deriving Eq// will check if 2 objects are identical. For our data, you'll have to provide a custom '==' such that: | ||
* list1 == list2 = True if both trees have the same elements, but in any order | * list1 == list2 = True if both trees have the same elements, but in any order | ||
* tree1 == tree2 = True if both trees have the same elements, but in any order | * tree1 == tree2 = True if both trees have the same elements, but in any order | ||
- | * stud1 == stud2 = True if both students have the same average on their grades | + | * stud1 == stud2 = True if both students have the same average on their grades, same last_names and same first_names |
Line 60: | Line 63: | ||
- | 4. Let's sort students now. Add the student to the ''Ord'' class and provide implementations for ''<''. The criteria will be their grades average, maximum grade, last_name, and first_name alphabetical. | + | 4. Let's sort students now. Add the student to the ''Ord'' class and provide implementations for ''<''. The criteria will be their grades average, maximum grade, last_name, and first_name alphabetical. We will sort them by rankings. //stud1 < stud2// if //stud1// is better than //stud2// by the above criteria. |
+ | === Custom Classes === | ||
+ | |||
+ | What if we need to create our own classes? For a quick example, we would like a class that tells us if a data type is Empty or not. We will call this class ''IsVoid'' and all types enrolled in this class must implement the ''isVoid'' method. | ||
+ | <code haskell> | ||
+ | class IsVoid a where | ||
+ | isVoid :: a -> Bool | ||
+ | |||
+ | instance IsVoid Bool where | ||
+ | isVoid False = True | ||
+ | isVoid True = False | ||
+ | |||
+ | instance IsVoid (BTree a) where | ||
+ | isVoid Void = True | ||
+ | isVoid _ = False | ||
+ | |||
+ | instance IsVoid [a] where | ||
+ | isVoid [] = True | ||
+ | isVoid _ = False | ||
+ | </code> | ||
+ | As you can see, now we can add our data types in the new class, but also Haskell's types. The only requirement is that the enrolled type must implement our method. | ||
+ | |||
+ | 5. Create a class ''Contains b a'' that will require a ''contains :: b -> a -> Bool'' method which will return True if ''a'' is in ''b''. Add ''[a]'', ''List a'' and ''BTree a'' to this class. | ||
+ | <note tip>Do we need any additional restrictions for a or b? You can still add restrictions: | ||
+ | <code haskell> | ||
+ | class (SomeClass a) => Contains b a where ... | ||
+ | </code></note> | ||
+ | 6. Create the ''class Size a'' which will require the methods ''size'' and ''uniqueSize''. Add ''[a]'', ''List a'' and ''BTree a'' to this class. | ||
+ | - //size// = the numbers of elements in **a** | ||
+ | - //uniqueSize// = the number of uniqueElements in **a** |