P. 1
Haskel Tutorial

Haskel Tutorial

|Views: 132|Likes:
Publicado pordevilvsevil

More info:

Published by: devilvsevil on Oct 23, 2008
Direitos Autorais:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

09/07/2012

pdf

text

original

Consider a datatype whose purpose is to hold configuration settings. Usually when
you extract members from this type, you really only care about one or possibly two of
the many settings. Moreover, if many of the settings have the same type, you might
often find yourself wondering “wait, was this the fourth or fifth element?” One thing
you could do would be to write accessor functions. Consider the following made-up
configuration type for a terminal program:

data Configuration =
Configuration String

-- user name

String

-- local host

String

-- remote host

Bool

-- is guest?

Bool

-- is super user?

String

-- current directory

String

-- home directory

Integer

-- time connected

deriving (Eq, Show)

You could then write accessor functions, like (I’ve only listed a few):

getUserName (Configuration un _ _ _ _ _ _ _) = un
getLocalHost (Configuration _ lh _ _ _ _ _ _) = lh
getRemoteHost (Configuration _ _ rh _ _ _ _ _) = rh

7.7. DATATYPES REVISITED

91

getIsGuest (Configuration _ _ _ ig _ _ _ _) = ig
...

You could also write update functions to update a single element. Of course, now
if you add an element to the configuration, or remove one, all of these functions now
have to take a different number of arguments. This is highly annoying and is an easy
place for bugs to slip in. However, there’s a solution. We simply give names to the
fields in the datatype declaration, as follows:

data Configuration =
Configuration { username

:: String,

localhost

:: String,
remotehost :: String,
isguest

:: Bool,
issuperuser :: Bool,
currentdir :: String,
homedir

:: String,
timeconnected :: Integer

}

This will automatically generate the following accessor functions for us:

username :: Configuration -> String
localhost :: Configuration -> String
...

Moreover, it gives us very convenient update methods. Here is a short example
for a “post working directory” and “change directory” like functions that work on
Configurations:

changeDir :: Configuration -> String -> Configuration
changeDir cfg newDir =
-- make sure the directory exists
if directoryExists newDir
then -- change our current directory
cfg{currentdir = newDir}
else error "directory does not exist"

postWorkingDir :: Configuration -> String
-- retrieve our current directory
postWorkingDir cfg = currentdir cfg

So, in general, to update the field x in a datatype y to z, you write y{x=z}. You
can change more than one; each should be separated by commas, for instance,y{x=z,
a=b, c=d}.

92

CHAPTER 7. ADVANCED FEATURES

You can of course continue to pattern match against Configurations as you did
before. The named fields are simply syntactic sugar; you can still write something like:

getUserName (Configuration un _ _ _ _ _ _ _) = un

But there is little reason to. Finally, you can pattern match against named fields as

in:

getHostData (Configuration {localhost=lh,remotehost=rh})
= (lh,rh)

This matches the variable lh against the localhost field on the Configuration
and the variable rh against the remotehost field on the Configuration. These
matches of course succeed. You could also constrain the matches by putting values
instead of variable names in these positions, as you would for standard datatypes.
YoucancreatevaluesofConfigurationintheoldwayasshowninthefirstdefinition
below, or in the named-field’s type, as shown in the second definition below:

initCFG =

Configuration "nobody" "nowhere" "nowhere"
False False "/" "/" 0

initCFG’ =

Configuration
{ username="nobody",
localhost="nowhere",
remotehost="nowhere",
isguest=False,
issuperuser=False,
currentdir="/",
homedir="/",
timeconnected=0 }

Though the second is probably much more understandable unless you litter your

code with comments.

You're Reading a Free Preview

Descarregar
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->