1. Type Inference To generate the type inference tree, generate a parse tree for a function. The easiest way to do this is to generate a curried lambda function for our function. fun w (x, y, z) = x(y(z)) + 2 could be written as L x . L y . L z . (((+) (x (y z))) 2) where we have curried + There are two basic type-inference rules: Application: The application of a function takes its right sibling as input and results in the type of its parent Lambda: A lambda node takes its left children as input and results in its right child type (The text book has a good descriptions and illustrations of these rules in action) 2. Typeclasses Typeclasses are similar to interfaces in Java. They have a number of functions that may be implemented by a data type, so that that data type becomes an instance of the typeclass. The general format is: data DataName = ... DataDefinition ... -- Typeclass definition class ClassName a where method1 :: type_of_method1 method2 :: type_of_method2 -- Instancing a typeclass instance ClassName DataName where method1 params = ... definition ... method2 params = ... definition ... Show and Read are typeclasses for generating strings from data or reading data from strings, respectively. The Typeclass is defined in the prelude, so all you have to do is instance these classes if you want to be able to display them on or read them from ghci. BEncoding is a method of encoding messages passed between BitTorrent clients. BEncoding encodes and decodes string messages. There are four types allowed in BEncoding: Integers, ByteStrings, Lists, and Dictionaries. For this exercise, we'll treat ByteStrings just like normal strings. The integer 34 would be encoded as with the prefix "i" and suffix "e", or i34e The string "happy" is encoded as its length, followed by the string itself, or 5:happy Lists are lists containing other BEncode types, and are prefixed with an "l" and suffixed with an "e". All the list items are encoded and listed one after another. The list ["1", 2, 3] would be encoded as l1:1i2ei3ee Dictionaries are a list of BEncoded pairs. They are similar in encoding to lists, they just use the prefix "d". The dictionary [(1, "2"), ("3", 4)] would be encoded as di1e1:21:3i4ee We can define this data type in Haskell as: data BEncode = Number { value::Int } | ByteString { byteData::String } | List { list::[BEncode] } | Dictionary { dictionary::[(BEncode, BEncode)] flattenPair :: (Show a) => (a, a) -> String flattenPair (x, y) = (show x) ++ (show y) --Here is our implementation of the show method from typeclass Show for the --BEncode data type. instance Show BEncode where show (Number x) = "i" ++ show(x) ++ "e" show (ByteString string) = show(length string) ++ ":" ++ string show (List l) = "l" ++ (foldl (++) "" (map show l)) ++ "e" show (Dictionary d) = "d" ++ (foldl (++) "" (map flattenPair d)) ++ "e" foldl functions as a left-reduce with an initial value passed in. Note that you could have just used concat to flatten all the lists, but I thought using map-reduce would be fun.