Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1.  Question regarding to type classes (Johannes Engels)
   2. Re:  Question regarding to type classes (Antoine Latter)
   3.  how to catch the error thrown by openFile? (Ovidiu Deac)
   4. Re:  Question regarding to type classes (Daniel Fischer)
   5. Re:  how more efficient read/write a file ? (Kyle Murphy)
   6.  Question regarding to type classes (Johannes Engels)
   7. Re:  how to catch the error thrown by openFile? (Daniel Fischer)
   8.   how to catch the error thrown by openFile? (Ovidiu Deac)


----------------------------------------------------------------------

Message: 1
Date: Sat, 24 Sep 2011 19:21:17 +0200
From: Johannes Engels <[email protected]>
Subject: [Haskell-beginners] Question regarding to type classes
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-15; format=flowed

Dear list members,

as an exercise, I tried to define a type class for structures with 
ordered key values. The key values could be numbers, but also strings. 
For instance, I intend to define an address list containing records with 
names as key values. So far, my type class definition contains a 
function "key", which should extract the key values from the structures, 
and a function which compares the key values. So I tried:

class StructsWithOrderedKeys a where
-- no default definition for key
    key :: (Ord b) => a -> b

    (<?) :: a -> a -> Bool
    x <? y = (key x) < (key y)

Here I get the following error message from GHCI:

"Ambiguous type variable 'b' in the constraint:
'Ord b' arising from a use of 'key' ...
Probable fix: add a type signature that fixes these type variable(s)"

Could anybody explain what ambiguity arises here? As the arguments of 
(<?) are of the same type, I expected also the results (key x) and (key 
y) to be of the same type, which should be by the type constraint for 
"key" an instance of Ord. Why I am not allowed to use "key" in the 
definition of (<?) ?

I would be grateful for any hint!
Johannes






------------------------------

Message: 2
Date: Sat, 24 Sep 2011 12:42:33 -0500
From: Antoine Latter <[email protected]>
Subject: Re: [Haskell-beginners] Question regarding to type classes
To: Johannes Engels <[email protected]>
Cc: [email protected]
Message-ID:
        <CAKjSnQEWXkFhUTYHSAGOH_O4wkmOysNO5jyCXY0g=30mdcc...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

On Sat, Sep 24, 2011 at 12:21 PM, Johannes Engels
<[email protected]> wrote:
> Dear list members,
>
> as an exercise, I tried to define a type class for structures with ordered
> key values. The key values could be numbers, but also strings. For instance,
> I intend to define an address list containing records with names as key
> values. So far, my type class definition contains a function "key", which
> should extract the key values from the structures, and a function which
> compares the key values. So I tried:
>
> class StructsWithOrderedKeys a where
> -- no default definition for key
> ? key :: (Ord b) => a -> b
>
> ? (<?) :: a -> a -> Bool
> ? x <? y = (key x) < (key y)
>
> Here I get the following error message from GHCI:
>
> "Ambiguous type variable 'b' in the constraint:
> 'Ord b' arising from a use of 'key' ...
> Probable fix: add a type signature that fixes these type variable(s)"
>
> Could anybody explain what ambiguity arises here? As the arguments of (<?)
> are of the same type, I expected also the results (key x) and (key y) to be
> of the same type, which should be by the type constraint for "key" an
> instance of Ord. Why I am not allowed to use "key" in the definition of (<?)
> ?
>

If a function has type:

> key :: (Ord b) => a -> b

You have declared that the type 'b' can be whatever the caller wants
(given the Ord constraint).

So in the computations:

> (key x) > (key y)

You haven't told it *which* 'b' you want to pick. And because the
return value is consumed by a polymorphic function, the type inference
engine doesn't have anything to go on.

Does that make sense?

Antoine



------------------------------

Message: 3
Date: Sat, 24 Sep 2011 20:52:24 +0300
From: Ovidiu Deac <[email protected]>
Subject: [Haskell-beginners] how to catch the error thrown by
        openFile?
To: beginners <[email protected]>
Message-ID:
        <CAKVsE7tcR4Cs9Tk=VZOb1jqC=gkmkpk+cx8pu0q7o74sxa9...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

Given this function

f :: MyMonad String
f = do
  liftIO $ putStrLn "Please enter a file name: "
  name ?  liftIO getLine
  hFile ?  liftIO $ openFile name ReadMode
  content ?  liftIO $ hGetContents hFile
  return $ content

I would like to catch the error thrown by openFile and translate it to
my own exception type.

So first I tried this:
  hFile ?  (liftIO $ openFile name ReadMode) `catch` ?_ ?  throwError
(KnownErr "open failed")

..but it fails because the error handler is returning a different type
then the "try block". Right?

Then I tried this:
f = do
  liftIO $ putStrLn "Please enter a file name: "
  name ?  liftIO getLine
  hFile ?  (liftIO $ openFile name ReadMode ? return.Right)
                `catch` ?_ ? return (Left $ KnownErr "open failed")
  case hFile of
    Right handle ?  do
          content ?  liftIO $ hGetContents hFile
          return $ content
    Left error ?  throwError error

...which also fails with
    Couldn't match expected type `ErrorT MyType IO t0'
                with actual type `IO a0'
    In a stmt of a 'do' expression:
        hFile <- (do { handle <- liftIO $ openFile name ReadMode;
                       return (Right handle) })
               `catch`
                 \ _ -> return (Left $ KnownErr "open failed")

Any help is appreciated.

Thanks!


Full code here:

import Control.Monad.Error
import System.IO

data MyType = UnknownErr | KnownErr String
    deriving (Show)

instance Error MyType where
    noMsg = UnknownErr
    strMsg str = KnownErr str

type MyMonad = ErrorT MyType IO

main = do
  r ?  runErrorT f
  reportResult r

f :: MyMonad String
f = do
  liftIO $ putStrLn "Please enter a file name: "
  name ?  liftIO getLine
  hFile ?  liftIO $ openFile name ReadMode
  content ?  liftIO $ hGetContents hFile
  return $ content

reportResult (Right c) = putStrLn ("The content is " ? c)
reportResult (Left e) = putStrLn ("Error: " ? (show e))



------------------------------

Message: 4
Date: Sat, 24 Sep 2011 19:52:49 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] Question regarding to type classes
To: [email protected]
Cc: Johannes Engels <[email protected]>
Message-ID: <[email protected]>
Content-Type: Text/Plain;  charset="iso-8859-1"

On Saturday 24 September 2011, 19:21:17, Johannes Engels wrote:
> Dear list members,
> 
> as an exercise, I tried to define a type class for structures with
> ordered key values. The key values could be numbers, but also strings.
> For instance, I intend to define an address list containing records with
> names as key values. So far, my type class definition contains a
> function "key", which should extract the key values from the structures,
> and a function which compares the key values. So I tried:
> 
> class StructsWithOrderedKeys a where
> -- no default definition for key
>     key :: (Ord b) => a -> b

This does not mean what I think you intend.
This type signature means that key can produce any type belonging to Ord, 
whatever the caller desires.
So, I need a String, key can produce it, Bool? too, from the same value, 
Integer? yes, also that...

> 
>     (<?) :: a -> a -> Bool
>     x <? y = (key x) < (key y)
> 
> Here I get the following error message from GHCI:
> 
> "Ambiguous type variable 'b' in the constraint:
> 'Ord b' arising from a use of 'key' ...
> Probable fix: add a type signature that fixes these type variable(s)"
> 
> Could anybody explain what ambiguity arises here? As the arguments of
> (<?) are of the same type, I expected also the results (key x) and (key
> y) to be of the same type, which should be by the type constraint for
> "key" an instance of Ord. Why I am not allowed to use "key" in the
> definition of (<?) ?

Because, as said above, key's type says it can produce values of different 
types from the same argument, so the compiler can't know which type to 
pick, should it produce

  x <? y = (key x :: Integer) < key y

or

  x <? y = (key x :: String) < key y

or ...

So the type at which to do the comparison is ambiguous.

What you probably intended is that for every type s which is an instance of 
StructsWithOrderedKeys, there is a type k, belonging to Ord, such that the 
function key produces values of type k from values of type s.

You can achieve that by using multiparameter type classes (with functional 
dependencies) or associated types.

With associated types, it would be

==========
{-# LANGUAGE TypeFamilies, FlexibleContexts #-}
module Structs where


class (Ord (Key a)) => StructsWithOrderedKeys a where
  type Key a
  key ::a -> Key a
  (<?) :: a -> a -> Bool
  x <? y = key x < key y

data Pair = P { pkey :: String, pval :: Int } deriving Show

instance StructsWithOrderedKeys Pair where
  type Key Pair = String
  key = pkey
==========

and with multiparameter type classes

==========
{-# LANGUAGE MultiParamTypeClasses, FunctionalDependencies #-}
module Structs where

-- The "| a -> b" is the functional dependency saying that a
-- uniquely determines b
class (Ord b) => StructsWithOrderedKeys a b | a -> b where
  key :: a -> b
  (<?) :: a -> a -> Bool
  x <? y = key x < key y

data Pair = P { pkey :: String, pval :: Int } deriving Show

instance StructsWithOrderedKeys Pair String where
  key = pkey
=========

Use what you prefer, some things are easier to express using FunDeps, 
others using associated types.
Generally, FunDeps were there first, but people tend to rather use type 
families nowadays.



------------------------------

Message: 5
Date: Sat, 24 Sep 2011 14:00:24 -0400
From: Kyle Murphy <[email protected]>
Subject: Re: [Haskell-beginners] how more efficient read/write a file
        ?
To: Benjamin Edwards <[email protected]>
Cc: Beginners <[email protected]>
Message-ID:
        <CA+y6JcxV3DP6L0+moyhW3QNvZ12qZPitoXL6fV8=17yp-73...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

It's not for the faint of heart, but the enumerator package is also supposed
to provide very good performance for stream transformations. I've looked at
it a bit myself but I'm still struggling to wrap my head around the types
involved, which like most things in Haskell is the key to understanding the
whole thing.

-R. Kyle Murphy
--
Curiosity was framed, Ignorance killed the cat.


On Sat, Sep 24, 2011 at 05:01, Benjamin Edwards <[email protected]>wrote:

> You should look up bytestring and friends on hackage.
>
> If it is something quite simple you can use the lazy variants and provided
> that you don't try to hold onto the input you should get nice constant space
> without trying too hard.
>
> I recommend the early chapters on IO in real world haskell if you want more
> info on lazy IO.
> On 24 Sep 2011 03:06, "anyzhen" <[email protected]> wrote:
> > consider this :
> > i want load a 4G file(or some bigger file) ,and the process data
> operation just like 010 to 101( XOR bits ) , is it some efficient function
> down it ?
> > such hPutStr hPutChar is Char layer , is exist bit layer operations?
> >
> >
> > thanks for any help
> >
> >
> > [email protected]
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20110924/917c28e3/attachment-0001.htm>

------------------------------

Message: 6
Date: Sat, 24 Sep 2011 20:12:10 +0200
From: Johannes Engels <[email protected]>
Subject: [Haskell-beginners] Question regarding to type classes
To: [email protected]
Message-ID: <[email protected]>
Content-Type: text/plain; charset=ISO-8859-15; format=flowed

Thank you very much, Antoine Latter and, particularly, Daniel Fischer 
for your excellent explanation! You have exactly understood what I 
intended and answered my question completely, so you really made my day!

Johannes








------------------------------

Message: 7
Date: Sat, 24 Sep 2011 21:21:59 +0200
From: Daniel Fischer <[email protected]>
Subject: Re: [Haskell-beginners] how to catch the error thrown by
        openFile?
To: [email protected]
Message-ID: <[email protected]>
Content-Type: Text/Plain;  charset="utf-8"

On Saturday 24 September 2011, 19:52:24, Ovidiu Deac wrote:
> Given this function
> 
> f :: MyMonad String
> f = do
>   liftIO $ putStrLn "Please enter a file name: "
>   name ?  liftIO getLine
>   hFile ?  liftIO $ openFile name ReadMode
>   content ?  liftIO $ hGetContents hFile
>   return $ content
> 
> I would like to catch the error thrown by openFile and translate it to
> my own exception type.
> 
> So first I tried this:
>   hFile ?  (liftIO $ openFile name ReadMode) `catch` ?_ ?  throwError
> (KnownErr "open failed")

catch has type (IO a -> (e -> IO a) -> IO a) [where e = IOError if you're 
using Prelude.catch, and e can be any instance of Exception if you're using 
Control.Exception.catch (recommended)].

But (liftIO ioAction) has type (MyMonad a), so that can't be used as an 
argument to catch.
Nor can (\_ -> throwError (KnownErr "...")).

> 
> ..but it fails because the error handler is returning a different type
> then the "try block". Right?

No, it fails because both have the wrong type for catch.
It would typecheck with catchError instead of catch, but that wouldn't 
catch the error :(

> 
> Then I tried this:
> f = do
>   liftIO $ putStrLn "Please enter a file name: "
>   name ?  liftIO getLine
>   hFile ?  (liftIO $ openFile name ReadMode ? return.Right)
>                 `catch` ?_ ? return (Left $ KnownErr "open failed")

Close. If you replace liftIO with ErrorT in that line and move the first 
open parenthesis past the $, then it works and does what you want. Without 
changing the following two lines (or, better, do change them;
do x <- act
   return x

is the same as just

act
). liftIO adds a layer of Either, ErrorT doesn't.

  hFile <- ErrorT $ liftM Right (openFile name ReadMode)
       `catch` (\_ -> return $ Left (KnownErr "open failed"))
  liftIO $ hGetContents hFile



------------------------------

Message: 8
Date: Sun, 25 Sep 2011 01:27:54 +0300
From: Ovidiu Deac <[email protected]>
Subject: [Haskell-beginners]  how to catch the error thrown by
        openFile?
To: beginners <[email protected]>
Message-ID:
        <CAKVsE7tYTybBNd4QhN2V1=sJ8oPFJw6j0YNn=qG0S97JV7z=z...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

Thanks a lot! It took me a while to understand what you meant but
eventually I got it.

This is the final version and it looks much better:

f :: MyMonad String
f = do
?liftIO $ putStrLn "Please enter a file name: "
?name ? ?liftIO getLine
?hFile ? ?ErrorT $ (openFile name ReadMode ? return.Right)
? ? ? ? ? ? ? ?`catch` ?_ ? return.Left $ KnownErr "open failed"
?content ? ?liftIO $ hGetContents hFile
?return content

Somehow I understand but I don't have the feeling yet why I apply
ErrorT to the whole catched expression instead of liftIO. Do you have
a nice explanation for it?

Ovidiu

On Sat, Sep 24, 2011 at 10:21 PM, Daniel Fischer
<[email protected]> wrote:
> On Saturday 24 September 2011, 19:52:24, Ovidiu Deac wrote:
>> Given this function
>>
>> f :: MyMonad String
>> f = do
>> ? liftIO $ putStrLn "Please enter a file name: "
>> ? name ? ?liftIO getLine
>> ? hFile ? ?liftIO $ openFile name ReadMode
>> ? content ? ?liftIO $ hGetContents hFile
>> ? return $ content
>>
>> I would like to catch the error thrown by openFile and translate it to
>> my own exception type.
>>
>> So first I tried this:
>> ? hFile ? ?(liftIO $ openFile name ReadMode) `catch` ?_ ? ?throwError
>> (KnownErr "open failed")
>
> catch has type (IO a -> (e -> IO a) -> IO a) [where e = IOError if you're
> using Prelude.catch, and e can be any instance of Exception if you're using
> Control.Exception.catch (recommended)].
>
> But (liftIO ioAction) has type (MyMonad a), so that can't be used as an
> argument to catch.
> Nor can (\_ -> throwError (KnownErr "...")).
>
>>
>> ..but it fails because the error handler is returning a different type
>> then the "try block". Right?
>
> No, it fails because both have the wrong type for catch.
> It would typecheck with catchError instead of catch, but that wouldn't
> catch the error :(
>
>>
>> Then I tried this:
>> f = do
>> ? liftIO $ putStrLn "Please enter a file name: "
>> ? name ? ?liftIO getLine
>> ? hFile ? ?(liftIO $ openFile name ReadMode ? return.Right)
>> ? ? ? ? ? ? ? ? `catch` ?_ ? return (Left $ KnownErr "open failed")
>
> Close. If you replace liftIO with ErrorT in that line and move the first
> open parenthesis past the $, then it works and does what you want. Without
> changing the following two lines (or, better, do change them;
> do x <- act
> ? return x
>
> is the same as just
>
> act
> ). liftIO adds a layer of Either, ErrorT doesn't.
>
> ?hFile <- ErrorT $ liftM Right (openFile name ReadMode)
> ? ? ? `catch` (\_ -> return $ Left (KnownErr "open failed"))
> ?liftIO $ hGetContents hFile
>



------------------------------

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


End of Beginners Digest, Vol 39, Issue 29
*****************************************

Reply via email to