Let’s make an Elemental Battle System in Haskell – Part IV

You can call this “EBS v. 3.5”, because I’m not showing here so much big improvements. I’m gonna focus on two main points:

  1. Some little refactoring (thanks to your comments)
  2. Implementation of custom spell behavior

A little less refactoring

Our already discussed isWeakTo and isStrongAgainst functions were relying on pattern matching in this fashion:

isWeakTo :: TargetableUnit -> Maybe Element -> Maybe Bool
m `isWeakTo` elem = case elem of
                         Just e -> checkProperty m ((==e) . succ)
                         _ -> Nothing

Uhm.. we are continuously putting in and getting out things from a context.. yes, this is a work for ours lovely Monads!

isWeakTo :: TargetableUnit -> Maybe Element -> Maybe Bool
m `isWeakTo` elem = elem >>= (\e -> checkProperty m ((==e) . succ))

Cool! Only two lines! But what are we really doing? Well, we take a value within a context (a Maybe Element) and we give it for lunch to our >>= operator: it takes our elem, unbox it (revealing an Element e or Nothing if nothing’s there), and giving it to our checkProperty function for dinner. We don’t have to put the result into a context again, because checkProperty returns a Maybe Bool, i.e. a Bool inside the failure context (Maybe). Pretty cool, isn’t it? Same applies for isStrongAgainst

A custom spell behavior

So far we have created a Spell, to cast against some TargetableUnit: we have a simple function called cast that takes a Spell and a TargetableUnit, and does the dirty job:

cast :: Spell -> TargetableUnit -> TargetableUnit
cast s t =
    let coeff = getDmgMult t (spellElem s)
        in case spellEffect s of
            Damage hit mana -> t {hp = hp t - floor (fromIntegral hit * coeff),
                                  mp = mp t - floor (fromIntegral mana * coeff)}
            Inflict statList -> let sList = status t
                                    in t {status = nub (sList ++ statList)}

But our spell type is quite limited: it can only inflict some damage or some status. As you may remember, some cool spells, or items, could do some special tricks based, for example on the target life. Let’s take two examples:

  1. An Elixir – Fully restores HP/MP
  2. The Laser spell (Do you remember? you can learn it from enemies through the Enemy Skill materia in FFVII) – cut by half enemy’s life

How can we do to implement this custom behavior? Fortunately,  the solution is pretty easy: let’s add a brand new SpellEffect!

--Essentially the result of a spell cast
data SpellEffect = Damage HitPoints ManaPoints
                 | Inflict [Status]
                 | Custom (TargetableUnit -> TargetableUnit)

--Essentially a magic
data Spell = Spell{spellName :: String,
                   spellDesc :: String,
                   spellCost :: Integer,
                   spellElem :: Maybe Element,
                   spellEffect :: SpellEffect}

instance Show Spell where
    show x = spellDesc x

Note: I’ve added the spellDesc because it can be pretty-printed with show. What have we done? We are currently saying that a Spell can do three things:

  1. Deals damage
  2. Inflicts some status
  3. A custom behavior, i.e. a function we could define and that be used to perform actions based of target properties!!
Let’s see how this reflects to our cast and use functions:
cast :: Spell -> TargetableUnit -> TargetableUnit
cast s t =
    let coeff = getDmgMult t (spellElem s)
        in case spellEffect s of
            Damage hit mana -> t {hp = hp t - floor (fromIntegral hit * coeff),
                                  mp = mp t - floor (fromIntegral mana * coeff)}
            Inflict statList -> let sList = status t
                                    in t {status = nub (sList ++ statList)}
            Custom f -> f $ t

--(INSIDE Item.hs)
data ItemEffect = Restore HitPoints ManaPoints
                | Cure [Status]
                | Custom (TargetableUnit -> TargetableUnit)

--Use the item i on the target t
use :: Item -> TargetableUnit -> TargetableUnit
use i t = case (itemEffect i) of
               (Restore hp' mp') -> t {hp = hp t + hp', mp = mp t + mp'}
               (Cure rList) -> t {status = filter (\s -> s `notElem` rList) $ status t}
               (Custom f) -> f $ t

Obviously same applies to Item type. Ok, cool! So let’s define 1 item and 1 spell, what about an Elixir and the laser spell?

--Inside Item.hs
elixirBehaviour :: TargetableUnit -> TargetableUnit
elixirBehaviour t = t {hp = maxHp t, mp = maxMp t}
elixir = Item "Elixir" "Fully restores HP and MP" (Custom elixirBehaviour)

--Inside Spell.hs
laserBehaviour :: TargetableUnit -> TargetableUnit
laserBehaviour t = t {hp = floor $ (fromIntegral $ maxHp t) / 2.0}
laser = Spell "Laser" "Cut by half target's health" 20 Nothing (Custom laserBehaviour)

Ok, now it’s time for the meat: let’s test them!

Ok, modules loaded: EBS.Main, EBS.Elemental, EBS.Target, EBS.Status, EBS.Spell, EBS.Item, EBS.MonsterPark.
ghci> piros
Unit {name = "Piros", level = 1, hp = 300, maxHp = 300, mp = 50, maxMp = 50, strength = 10, dexterity = 10, vitality = 10, magic = 10, spirit = 10, luck = 10, elemType = Just Fire, status = []}
ghci> let damaged_piros = cast laser piros
ghci> damaged_piros
Unit {name = "Piros", level = 1, hp = 150, maxHp = 300, mp = 50, maxMp = 50, strength = 10, dexterity = 10, vitality = 10, magic = 10, spirit = 10, luck = 10, elemType = Just Fire, status = []}
ghci> use elixir piros
Unit {name = "Piros", level = 1, hp = 300, maxHp = 300, mp = 50, maxMp = 50, strength = 10, dexterity = 10, vitality = 10, magic = 10, spirit = 10, luck = 10, elemType = Just Fire, status = []}

Wow, they works! The lamba wizard seems to approve:

Ah, bear in mind that I’ve changed the minimal context value of the Spell status to be [] (empty list), because [] is the minimal context for the lists, and we can use cool Monads tricks as usual!

Git repo is in the same place! Enjoy!

Alfredo

Book review: Learn You a Haskell for Great Good!

Hi everyone,

this is the first book I write about, but it’s so well written and amusing that I’ve decided to blog my personal review.

As it started

Well, let’s start from the basics: Learn You a Haskell  is an amazing book  you can read online for free, or even buy the printed edition (as I did). In my opinion it’s definitely the best book on Haskell around. I stumbled  upon this book accidentally: I was just bored, looking for some new cool programming language to learn. I’ve already met Haskell six months ago, but it rapidly lost in interest because I judged it too weird and complicated, studying it on the famous “Real World Haskell“. Meanwhile, I’ve played a lot with Clojure and Lispy stuff. One day, I decided that I want to learn a language not only cool, expressive and functional as Clojure, but that I wanted a language to be fast and that can be compile cross platform (and functional, of course!) so I’ve thought about Haskell. Looking around into the books panorama, I found the site and the book: when I saw that it was edited by the amazing No Starch Press, featuring also the awesome Land of Lisp, I had no more doubt, I just bought it!

From rookie to master in 15 colorful chapters

This book is a little miracle indeed: you start thinking “Oh my God I’m an Haskell newbie, I won’t grasp Monads and other scaring stuff” and you finished thinking “So this are Monads about? They are so simple, it can be!”. The author guides you through all 15 chapters with a step-to-step approach: your path from functors to monads is built brick after brick. The amusing thing is that I’m reading it (indeed I haven’t finished it yet, 30 pages left 😛 ) at night just before going to sleep, and it’s so clear and simple that I can even understand everything!

Technically speaking, this book simply saved Haskell for me: before it, I considered Haskell a not-so-cool functional language, but this book changed everything.

The book, squeezed up

I’ve decided to go a step further into this book review, summarizing and giving an opinion of every book’s chapter:

  1. Starting Out: Your first Haskell file, plus a lot of cool stuff, e.g. ranges and list comprehensions. You will end thinking “Why I need range(1,20) or “for i = 0; i < 20; i++” when I have 1 .. 20? List comprehensions are awesome, too.
  2. Types and Typeclasses: Some Haskell’s basic types acquaintance. You will go deeper into the topic starting to Chp. 7
  3. Syntax in Functions: some basic syntax you can live without. You can already write some non-trivial functions, in my opinion; they will be a little verbose, but correct.
  4. Recursion: If you are familiar with functional language, go swiftly and fast through this.
  5. Higher Order Functions: the Haskell awesomeness begin to emerge. Haskell is a language where you have some kind of cool stuff just out-the-box: currying, lazyness and more. Sure, they come with a price, but come on, just enjoy them meanwhile!
  6. Modules: you will struggle with modules, and this chapter helps you to get thing a little less painful.
  7. Making Our Own Types and Typeclasses: by far, one of most important chapter: if you wanna do serious Haskell development make sure to squeeze out this chapter and the beautiful Haskell Type System. As a bonus, your first encounter with Functors!
  8. Input and Output: a light and pleasant chapter about Haskell IO. My advice is to skip this chapter and the next one for now. Come back with your overpowered Monad knowledge, and things will be much clearer (despite the fact they are clear even without any preliminar Monad knowledge).
  9. More input and output: I don’t know why, this chapter is not present into the online version: the author preferred to merge its content into the Chp. 8 (see above).
  10. Functionally Solving Problems: You can skip this, a collection of problems solved with functional thinking. Useful to take a pause and do some practice.
  11. Functors, Applicative Functors and Monoids: Here the author have merged all the cool stuff into this chapter, but into the printed version Chp. 11 is just “Applicative Functors”, and it’s only dedicated to that topic. Strange. In this extra-condensed chapter you will encounter functors, applicative functors (beefed-up functors) and monoid (for wrapping existing types). With them you will be finally able to respond to this question “What the hell Maybe is useful about?”
  12. A Fistful of Monads: Correspond to the book’s 13th Chapter. You will finally meet the legendary creature of Haskell programming: the powerful and terrifying Monad (I don’t why I thing to a Monad as a tibetan Monk).
  13. For a Few Monads More: After having grasped what monads are about, you’ll met useful and fantastic Monad, such as Writer, Reader and the atomic-one: the State Monad!
  14. Zippers: Perfect conclusion for the book; learn to use powerful Haskell functions based on Monoids and Monads

Conclusion

Learn You a Haskell is an amazing book, written by a very passionate author, for a fantastic programming language, Haskell. Give them both a try, you won’t regret! After all, Ada language is used into mission critial software, and Haskell has been influenced by Ada: This can’t be for accident, after all, don’t you believe?

See you!

Alfredo

Let’s make an Elemental Battle System in Haskell – Part III

Hi everyone,

in the last post we have played a bit with TargetableUnit(s) and cast some spell over some poor old monster. Now it’s the time to go a step further into the development of our mini system and add another useful piece of gameplay: Items!
With items you can  cure altered status and/or restore health and mana points. As you may guess, we are going to model Items just as usual, through records:

import EBS.Target
import EBS.Status
import Control.Applicative

data Item = Item{itemName :: String,
				         itemDesc :: String,
                 itemEffect :: ItemEffect} deriving (Show)

data ItemEffect = Restore HitPoints ManaPoints
                | Cure [Status] deriving (Show)

--Use the item i on the target t
use :: Item -> TargetableUnit -> TargetableUnit
use i t = case (itemEffect i) of
               (Restore hp' mp')  -> t {hp = hp t + hp', mp = mp t + mp'}
               (Cure rList) -> let newStatus = filter (\s -> s `notElem` rList) <$> (status t)
                                      in case newStatus of
                                              (Just []) -> t {status = Nothing}
                                              _ -> t {status = newStatus}

--Some Items
potion = Item "Potion" "Restores 100 HP" (Restore 100 0)
ether = Item "Ether" "Restores 100 MP" (Restore 0 100)
antidote = Item "Antidote" "Cures Poison status" (Cure [Poison])

Ok, so what I have done here? Simply I’ve created a new type, an Item, with name, description and the item effect, i.e. what happens when an item is used upon a TargetableUnit. As you can see, an Item can restore a certain amount of HitPoints or ManaPoints as well as cure some altered status. Let’s take a look to our use function:

--Use the item i on the target t
use :: Item -> TargetableUnit -> TargetableUnit
use i t = case (itemEffect i) of
               (Restore hp' mp')  -> t {hp = hp t + hp', mp = mp t + mp'}
               (Cure rList) -> let newStatus = filter (\s -> s `notElem` rList) <$> (status t)
                                      in case newStatus of
                                              (Just []) -> t {status = Nothing}
                                              _ -> t {status = newStatus}

It takes an Item, a TargetableUnit and returns a new TargetableUnit, that will be healed or cured from some status. The most interesting part of this function is the second branch of the first case expression, when we manage the case (Cure rList): Essentially we have a TargetableUnit that can be or not affected by some status (I remember you that status is modeled as status :: Maybe [Status]) but we don’t know a priori if that unit have some altered status or not. We’ll use applicative functors to smartly get rid of cured status: we’re filtering the list of status leaving only those status who are not present into the rList (the list who contains the status cured by that item). We use the fmap alias, <$>, to put our function into the Maybe context: we’ll obtain either the new status list, or Nothing is the unit was not affacted by any status (therefore there wasn’t any status to cure). One special case: if we cure all the unit’s status we’ll obtain an empty list, but we want a Nothing value instead, so we have to handle this case properly (see the last case expression).

Gimme some modifier

One flaw of our Battle System was that every spell dealt always the same amount of damage, ignoring inter-element weakness or strengths.  This new version of the cast spell handles this: if some unit is weak against some element, the correspondent spell will deal double damage, converse applies, with only half damage dealt to a unit strong against some element:

--cast function
cast :: Spell -> TargetableUnit -> TargetableUnit
cast s t =
    let coeff = getDmgMult t (spellElem s)
        in case spellEffect s of
            Damage hit mana -> t {hp = hp t - floor (fromIntegral hit * coeff),
                                  mp = mp t - floor (fromIntegral mana * coeff)}
            Inflict statList -> case (status t) of
                                     (Just sList) -> t {status = Just $ nub (sList ++ statList)}
                                     Nothing -> t {status = Just statList}

--the damage multiplier function
--Ugly, can I do better?
getDmgMult :: TargetableUnit -> Maybe Element -> Double
getDmgMult t e = case t `isWeakTo` e of
                      Just True -> 2.0
                      Just False -> case t `isStrongAgainst` e of
                                         Just True -> 0.5
                                         Just False -> 1.0
                                         _ -> 1.0
                      _ -> 1.0

Probably I haven’t grasp all the advanced Haskell concept yet, because this function look a little ugly and too pattern matching dependent, but I couldn’t do better. In order to make this works we need to modify our “isWeakTo” and “isStrongAgainst” function in order to accept a Maybe Element: it quite makes sense if you think about it, because no Element translates into a Nothing value:

--If the monster hasn't got any element, the result will be Nothing.
isWeakTo :: TargetableUnit -> Maybe Element -> Maybe Bool
m `isWeakTo` elem = case elem of
                         Just e -> checkProperty m ((==e) . succ)
                         _ -> Nothing

isStrongAgainst :: TargetableUnit -> Maybe Element -> Maybe Bool
m `isStrongAgainst` elem = case elem of
                                Just e -> checkProperty m ((==e) . pred)
                                _ -> Nothing

Ok! So we have monsters, we have some spells and some items, we can damage monster or even heal them (such a fool action!).
Let’s give this code a try:

ghci> :l EBS/Main.hs
[1 of 7] Compiling EBS.Status       ( EBS/Status.hs, interpreted )
[2 of 7] Compiling EBS.Elemental    ( EBS/Elemental.hs, interpreted )
[3 of 7] Compiling EBS.Target       ( EBS/Target.hs, interpreted )
[4 of 7] Compiling EBS.Item         ( EBS/Item.hs, interpreted )
[5 of 7] Compiling EBS.Spell        ( EBS/Spell.hs, interpreted )
[6 of 7] Compiling EBS.MonsterPark  ( EBS/MonsterPark.hs, interpreted )
[7 of 7] Compiling EBS.Main         ( EBS/Main.hs, interpreted )
Ok, modules loaded: EBS.Main, EBS.Elemental, EBS.Target, EBS.Status, EBS.Spell, EBS.Item, EBS.MonsterPark.
ghci> piros
Unit {name = "Piros", level = 1, hp = 300, mp = 50, elemType = Just Fire, status = Nothing}
ghci> let cursed_piros = cast frogSong piros
ghci> cursed_piros
Unit {name = "Piros", level = 1, hp = 300, mp = 50, elemType = Just Fire, status = Just [Frog,Sleep]}
ghci> use remedy cursed_piros
Unit {name = "Piros", level = 1, hp = 300, mp = 50, elemType = Just Fire, status = Just [Frog]}
--Wake up, Piros!
ghci> cast earth piros
Unit {name = "Piros", level = 1, hp = 0, mp = 50, elemType = Just Fire, status = Nothing}
--The original piros bind, double damage! (Earth deal 150 dmg, 300 to piros since it's weak to Earth)
ghci> cast fire piros
Unit {name = "Piros", level = 1, hp = 200, mp = 50, elemType = Just Fire, status = Nothing}
--Normal damage, 100 hp.

Now we miss only the most important thing: a Player!
Stay tuned!

Ah, I’ve opened yet another git repo here, so you can download the fully working code! Just run ghci into the parent directory and import the module in this way:

:l EBS/Main.hs

Enjoy!

Let’s make an Elemental Type System in Haskell – Part II

Ok, so we have our elements, our monster but we can do nothing more instancing some monster and checking for their weakness. We need to think about some design choices and how they could affect our program. The main drawback working with Haskell Records is the namespace pollution: you can’t define two distinct record with one or more fields names in common because Haskell will give you an error. This happens because Haskell under the hood converts that fields into global functions, so we can access our monster property just typing:

name myMonster

Pretty cool, but unfortunately we couldn’t do the same if we have defined another type, e.g. Player, with the same field.

Is everything lost? No! There are several workaround on the net, but thinking about our game I’ve discovered that isn’t a big problem to use a single type in order to model both a monster and a player: both have a name, hp, mp, level, and even a status:

data TargetableUnit = Unit{name :: String,
                           level :: Int,
                           hp :: HitPoints,
                           mp :: ManaPoints,
                           elemType :: Maybe Element,
                           status :: Maybe [Status]} deriving (Eq, Read, Show)

And what about elemType? “A Player can’t have an element!” you may say, but think about that: suppose you have just obtained a brand new ring (e.g. Tetra Elemental), that absorb one or more elemental damage.. with the elemeType field you can model this behaviour! Well, in this first version you can have only ONE Element, but changing Maybe Element in Maybe [Element] seems pretty straightforward. Ok, so we have our TargetableUnit, it’s the time to create some spells!

It’s a kind of magic

In order to have magic, we need to have spells, modeled as a type:

--Essentially the result of a spell cast
data SpellEffect = Damage HitPoints ManaPoints
                 | Inflict [Status] deriving (Show)

--Essentially a magic
data Spell = Spell{spellName :: String,
                   spellCost :: Integer,
                   spellElem :: Maybe Element,
                   spellEffect :: SpellEffect} deriving (Show)

--cast function
cast :: Spell -> TargetableUnit -> TargetableUnit
cast s t =
    case spellEffect s of
       Damage hit mana -> t {hp = hp t - hit, mp = mp t - mana}
       Inflict statList -> case (status t) of
                                (Just sList) -> t {status = Just (sList ++ statList)}
                                Nothing -> t {status = Just statList}

--SPELL DEFINITIONS
fire   = Spell "Fire"   20 (Just Fire) (Damage 100 0)
fira   = Spell "Fira"   40 (Just Fire) (Damage 200 0)
firaga = Spell "Firaga" 80 (Just Fire) (Damage 300 0)

bio = Spell "Bio" 20 Nothing (Inflict [Poison])
frogSong = Spell "Frog Song" 30 Nothing (Inflict [Frog, Sleep])

Ok, so what we have done? Essentially a magic does two thing:

  1. Deal damage
  2. Inflict one or more negative status
  3. Both

In this version just ignore the third case, we’ll work on that later. Now watch the SpellEffect definition: HitPoints and ManaPoints are simply two type synonym (they are Integer), and the type is pretty straightforward, isn’t it? A SpellEffect can be resolved or with Damage or with a status infliction. The Spell type reflect this, with the spellEffect leaved as last field. Nothing to say about the cast function: picks a spell, a TargetableUnit (so this function will be the same for a monster and for the player) and return a new unit (remember, no side effect allowed) with less hp/mp (in case of Damage) or with more status in case of Inflict.

Let’s play with our new system:

ghci> :l EBS/Main.hs
[1 of 5] Compiling EBS.Status       ( EBS/Status.hs, interpreted )
[2 of 5] Compiling EBS.Elemental    ( EBS/Elemental.hs, interpreted )
[3 of 5] Compiling EBS.Target       ( EBS/Target.hs, interpreted )
[4 of 5] Compiling EBS.Spell        ( EBS/Spell.hs, interpreted )
[5 of 5] Compiling EBS.Main         ( EBS/Main.hs, interpreted )
Ok, modules loaded: EBS.Main, EBS.Elemental, EBS.Target, EBS.Status, EBS.Spell.
ghci> let piros = Unit "Piros" 1 100 50 (Just Fire) Nothing
ghci> piros
Unit {name = "Piros", level = 1, hp = 100, mp = 50, elemType = Just Fire, status = Nothing}
ghci> cast bio piros
Unit {name = "Piros", level = 1, hp = 100, mp = 50, elemType = Just Fire, status = Just [Poison]}
ghci> let newMonster = cast bio piros
ghci> newMonster
Unit {name = "Piros", level = 1, hp = 100, mp = 50, elemType = Just Fire, status = Just [Poison]}
ghci> cast frogSong newMonster
Unit {name = "Piros", level = 1, hp = 100, mp = 50, elemType = Just Fire, status = Just [Poison,Frog,Sleep]}

Pretty cool, isn’t it? We are far from have a usable or fun mini game, but now we can cast spell on a monster!

I’ll create a git repo ASAP, so you will find the entire code there!

Stay tuned!

Alfredo

Let’s make an Elemental Type System in Haskell – Part I

Hello everyone,

recently I falled in love (again) with Haskell, and I’ve decided to start a simple toy project just to stretch my Haskell muscles fibers.
Meanwhile, I’ve started Final Fantasy VII again, so I thought to realize a simple Elemental Type System. I dunno how much this project will be complex, but a lot of fun awaits.

The elemental cycle

The first to do is to choose an Elemental cycle i.e. how elements influence each other. I’ve choose this simple schema (don’t blame me for the source):

For now just ignore the star in the center of the picture, for us “Fire is weak against Earth, strong against Lightning”. Ok, so we need a type representing our elements, and we need a circular one, because we want be free to invoke

pred

and

succ

without having our program to crash because we reach a boundary. Unfortunately, I haven’t found a better way to implement this without having to manually enum each element:

--We want a cyrcular enumeration for our elems
--so we can't rely on the Bounded type
data Element = Fire | Earth | Wind | Water | Lightning
  deriving (Eq, Ord, Show, Read)

instance Enum Element where
    toEnum 0 = Fire
    toEnum 1 = Earth
    toEnum 2 = Wind
    toEnum 3 = Water
    toEnum 4 = Lightning
    toEnum i = toEnum $ i `mod` 5

    fromEnum Fire = 0
    fromEnum Earth = 1
    fromEnum Wind = 2
    fromEnum Water = 3
    fromEnum Lightning = 4

    enumFromTo x y = map toEnum [a .. b']
      where a = fromEnum x
            b = fromEnum y
            b' = if a <= b then b else b + 5

    enumFromThen x1 x2 = error "enumFromThen not supported for Element"
    enumFromThenTo x1 x2 y = error "enumFromThenTo not supported for Element"

We haven’t done much yet, fun starts right on! The second step is create a monster type, through the record syntax, which allow to nicely get the type properties:

data Monster = Monster {name :: String,
                        hp :: Integer,
                        mp :: Integer,
                        elemType :: Maybe Element}
                        deriving (Eq, Read)

instance Show Monster where
    show m = "Name: " ++ name m ++ "\n" ++
             "HP: " ++ show (hp m) ++ "\n" ++
             "MP: " ++ show (mp m) ++ "\n" ++
             "Element: " ++ show (elemType m)

I’ve created an instance of Show for the type Monster for pretty printing purpose. Note how elemType is of type “Maybe Element”, just because not every monster is an elemental one! Using Maybe we can make our elemental system more flexible and less crash prone. The next step is to create four simple functions to play with monsters weakness and strenghts:

weakTo :: Monster -> Maybe Element
weakTo m = case elemType m of
                Just e -> Just $ succ e
                _ -> Nothing

strongAgainst :: Monster -> Maybe Element
strongAgainst m = case elemType m of
                       Just e -> Just $ pred e
                       _ -> Nothing

isWeakTo :: Monster -> Element -> Bool
m `isWeakTo` elem = case elemType m of
                         Just e -> elem == (succ e)
                         _ -> False

isStrongAgainst :: Monster -> Element -> Bool
m `isStrongAgainst` elem = case elemType m of
                                Just e -> elem == (pred e)
                                _ -> False

As you can see, the code is pretty straightforward. We can use our functions just like a sort of “Sense” spell, searching for monster weakness (I remember you that a spell can be more or less effective depending on the type of the target). This functions works but as you can see there is too much boilerplate code, since we are changing only a function (pred and succ) between the two. Function application operator comes in rescue:

checkProperty :: Monster -> (Element -> Element) -> Maybe Element
checkProperty m f = case elemType m of
                    Just e -> Just . f $ e
                    _ -> Nothing

checkProperty is our general purpose function who checks for monster weakness and strengths, and here are the new functions versions:

weakTo' :: Monster -> Maybe Element
weakTo' m = checkProperty m succ

strongAgainst' :: Monster -> Maybe Element
strongAgainst' m = checkProperty m pred

Wow, only one line of code! The dirty job is done by “checkProperty”, and you can write similar and shorten function even for isWeakTo and isStrongAgainst

Let’s test them!

Now the funniest part, let’s have some fun with ghci:

:l Types.hs
[1 of 1] Compiling Main             ( Types.hs, interpreted )
Ok, modules loaded: Main.
ghci> let piro = Monster{name = "Piro", hp = 70, mp = 200, elemType = Just Fire}
ghci> checkProperty piro succ
Just Earth
ghci> checkProperty piro pred
Just Lightning
ghci> :r
[1 of 1] Compiling Main             ( Types.hs, interpreted )
Ok, modules loaded: Main.
ghci> let piro = Monster{name = "Piro", hp = 70, mp = 200, elemType = Just Fire}
ghci> strongAgainst' piro
Just Lightning
ghci> weakTo' piro
Just Earth
ghci> let dragon = Monster{name = "Dragon", hp = 200, mp = 100, elemType = Nothing}
ghci> dragon `isWeakTo` Fire
False
ghci> piro `isWeakTo` Earth
True
ghci>dragon
Name: Dragon
HP: 200
MP: 100
Element: Nothing
ghci>piro
Name: Piro
HP: 70
MP: 200
Element: Just Fire

Stay tuned for other improvement! Have fun with Haskell!

Alfredo

Little pain(s) of being a Lion

If you have switched to Mac Os X Lion, you have to cohabit with some little issue deriving from update. I will update this list as far as I’ll discover the pair  <issue, solution>:

  1. If you use CUDA, you need to update it. Fortunately this can be done easily since NVIDIA have already published the developer driver here
  2. The git path seems to be broken. If you try “git” from bash you’ll get “command not found”. The solution is simply adding the path into the right file (e.g. .bash_profile): you can find the git executable in /usr/local/git/bin
  3. Mac OS X 10.7 Lion hides the ~/Library directory by default. This is easy to reverse with a terminal command:

    chflags nohidden ~/Library/

Stay tuned for other updates 🙂

Bye,

Alfredo

New personal site

After years thinking about it, finally I’ve done it: I’ve registered a custom domain (a simple URL redirect) and I’ve create an app on the popular cloud hosting site Heroku: it uses the new Clojure support feature and the new (and cool) Clojure mini MVC Framework Noir.

The site is a bit slow the first time you visit it, because the app is pushed out of cache after a period of inactivity, but man, it’s free!
I really like the site layout (and Jquery is too cool). What do you think about it? Let me know! Ah, here is the url, visit it!

www.alfredodinapoli.com