<font class="Apple-style-span" face="'courier new', monospace"><br><br></font><div class="gmail_quote"><font class="Apple-style-span" face="'courier new', monospace">On Wed, Mar 2, 2011 at 10:09 PM, Karthick Gururaj <span dir="ltr"><<a href="mailto:karthick.gururaj@gmail.com">karthick.gururaj@gmail.com</a>></span> wrote:<br>
</font><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><font class="Apple-style-span" face="'courier new', monospace">Hello,<br>
<br>
I'm learning Haskell from the extremely well written (and well<br>
illustrated as well!) tutorial - <a href="http://learnyouahaskell.com/chapters" target="_blank">http://learnyouahaskell.com/chapters</a>.<br>
I have couple of questions from my readings so far.<br>
<br>
In "typeclasses - 101"<br>
(<a href="http://learnyouahaskell.com/types-and-typeclasses#typeclasses-101" target="_blank">http://learnyouahaskell.com/types-and-typeclasses#typeclasses-101</a>),<br>
there is a paragraph that reads:<br>
Enum members are sequentially ordered types - they can be enumerated.<br>
The main advantage of the Enum typeclass is that we can use its types<br>
in list ranges. They also have defined successors and predecesors,<br>
which you can get with the succ and pred functions. Types in this<br>
class: (), Bool, Char, Ordering, Int, Integer, Float and Double.<br>
<br>
What is the "()" type? Does it refer to a tuple? How can tuple be<br>
ordered, let alone be enum'd?<br></font></blockquote><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace">Any set can be put into an order. That's the well-ordering principle. Basically, the most natural order for pairs is the lexicographical order. There are instances of the form:</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace">instance (Ord a, Ord b) => Ord (a,b)</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace">in GHC.Enum (if you're using GHC). You can also create Enum instances for pairs, but at least one of the "sides" must be bounded. Otherwise, the enumeration will have an uncomputable order-type (something like the order type of the rationals). Check out <a href="http://en.wikipedia.org/wiki/Order_type">http://en.wikipedia.org/wiki/Order_type</a> if you're interested in what all that "order type" stuff means.</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace">I wrote an instance for this very purpose the other day:</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div><div><div><font class="Apple-style-span" face="'courier new', monospace">-- An intuitive way to think about this is in terms of tables. Given datatypes</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">--</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- @</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- data X = A | B | C | D deriving ('Bounded', 'Enum', 'Eq', 'Ord', 'Show')</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- data Y = E | F | G deriving ('Bounded', 'Enum', 'Eq', 'Ord', 'Show')</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- @</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">--</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- we can form the table</font></div><div><font class="Apple-style-span" face="'courier new', monospace">--</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- @</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- (A, E) (A, F) (A, G)</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- (B, E) (B, F) (B, G)</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- (C, E) (C, F) (C, G)</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- (D, E) (D, F) (D, G)</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- @</font></div><div><font class="Apple-style-span" face="'courier new', monospace">--</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- in a natural lexicographical order. We simply require that there be a finite</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- number of columns, and allow an unbounded number of rows (in so far as the</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- lazy evaluation mechanism allows them). In even more practical terms, we require</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- a finite number of columns because we use that number to perform arithmetic.</font></div><div><font class="Apple-style-span" face="'courier new', monospace"><br>
</font></div><div><font class="Apple-style-span" face="'courier new', monospace">instance ( Bounded b</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> , Enum a</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> , Enum b</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> ) => Enum (a, b) where</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> toEnum k = let n = 1 + fromEnum (maxBound :: b) -- Enums are 0 indexed, but we want to</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> a = toEnum ((k `div` n)) -- divide by the number of elements in a row to find the row and</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> b = toEnum ((k `mod` n)) -- get the remainder to find the column.</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> in (a,b) </font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> </font></div><div><font class="Apple-style-span" face="'courier new', monospace"> fromEnum (a, b) = let n = 1 + fromEnum (maxBound :: b)</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> i = fromEnum a</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> j = fromEnum b</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> in (i*n + j)</font></div><div><font class="Apple-style-span" face="'courier new', monospace"><br></font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- | This instance of 'Enum' is defined in terms of the previous instance. We</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- use the natural equivalence of the types @(a,b,c)@ and @(a,(b,c))@ and use</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">-- the previous definition. Again, notice that all elements but the first must</font></div><div><font class="Apple-style-span" face="'courier new', monospace">-- be bounded.</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace">instance ( Bounded b</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> , Bounded c</font></div><div>
<font class="Apple-style-span" face="'courier new', monospace"> , Enum a</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> , Enum b</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> , Enum c</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> ) => Enum (a, b, c) where</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> fromEnum (a, b, c) = fromEnum (a, (b,c))</font></div>
<div><font class="Apple-style-span" face="'courier new', monospace"> toEnum k = let (a, (b, c)) = toEnum k</font></div><div><font class="Apple-style-span" face="'courier new', monospace"> in (a, b, c)</font></div>
<div> </div><div><font class="Apple-style-span" face="'courier new', monospace"> </font></div></div><div><br></div><div><br></div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
So tuples are in "Ord" type class atleast. What is the ordering logic?<br>
<br></blockquote><div><br></div><div>Lexicographical. Dictionary order. </div><div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Another question, on the curried functions - specifically for infix<br>
functions. Suppose I need a function that takes an argument and adds<br>
five to it. I can do:<br>
Prelude> let addFive = (+) 5<br>
Prelude> addFive 4<br>
9<br>
<br>
The paragraph: "Infix functions can also be partially applied by using<br>
sections. To section an infix function, simply surround it with<br>
parentheses and only supply a parameter on one side. That creates a<br>
function that takes one parameter and then applies it to the side<br>
that's missing an operand": describes a different syntax. I tried that<br>
as well:<br>
<br>
Prelude> let addFive' = (+5)<br>
Prelude> addFive' 3<br>
8<br>
<br>
Ok. Works. But on a non-commutative operation like division, we get:<br>
Prelude> let x = (/) 20.0<br>
Prelude> x 10<br>
2.0<br>
Prelude> let y = (/20.0)<br>
Prelude> y 10<br>
0.5<br>
<br>
So a curried infix operator fixes the first argument and a "sectioned<br>
infix" operator fixes the second argument?<br></blockquote><div><br></div><div>I guess, except you can section infix operators the other way:</div><div><br></div><div>> let twentyover = (20 /)</div><div><div>> twentyover 5</div>
<div>4.0</div></div></div>