Site Map - skip to main content

Hacker Public Radio

Your ideas, projects, opinions - podcasted.

New episodes every weekday Monday through Friday.
This page was generated by The HPR Robot at

hpr2818 :: Writing Web Game in Haskell - Science, part 1

Tuula explains types and data they used to model science in their Haskell game

<< First, < Previous, , Latest >>

Thumbnail of Tuula
Hosted by Tuula on 2019-05-22 is flagged as Clean and is released under a CC-BY-SA license.
Haskell. (Be the first).
The show is available on the Internet Archive at:

Listen in ogg, spx, or mp3 format. Play now:

Duration: 00:43:26


A series looking into the Haskell (programming language)


This is rather large topic, so I split it in two episodes. Next one should follow in two weeks if everything goes as planned. First part is about modeling research, while second part concentrates on how things change over time.

There’s three types of research: engineering, natural sciences and social sciences. Research costs points that are produced by various buildings.


There’s three database tables, which are defined below:

    type Technology
    progress Int
    factionId FactionId

    type Technology
    category TopResearchCategory
    factionId FactionId

    type Technology
    level Int
    factionId FactionId
    date Int

Data types

Technology is enumeration of all possible technologies. Knowing these enable player to build specific buildings and space ships, enact various laws and so on. In the end this will be (hopefully) large list of technologies.

data Technology =
    | SideChannelSensors
    | HighTensileMaterials
    | SatelliteTechnology
    | BawleyHulls
    | SchoonerHulls
    | CaravelHulls
    deriving (Show, Read, Eq, Enum, Bounded, Ord)

All research belong to one of the top categories that are shown below:

data TopResearchCategory =
    | NatSci
    | SocSci
    deriving (Show, Read, Eq, Ord)

ResearchCategory is more fine grained division of research. Each of the categories is further divided into sub-categories. Only EngineeringSubField is shown below, but other two are similarly divided.

data ResearchCategory =
    Engineering EngineeringSubField
    | NaturalScience NaturalScienceSubField
    | SocialScience SocialScienceSubField
    deriving (Show, Read, Eq)

data EngineeringSubField =
    | Materials
    | Propulsion
    | FieldManipulation
    deriving (Show, Read, Eq)

ResearchScore is measure of how big some research is. It has type parameter a that is used to further quantify what kind of ResearchScore we’re talking about.

newtype ResearchScore a = ResearchScore { unResearchScore :: Int }
    deriving (Show, Read, Eq, Ord, Num)

TotalResearchScore is record of three different types of researches. I’m not sure if I should keep it as a record of three fields or if I should change it so that only one of those values can be present at any given time.

data TotalResearchScore a = TotalResearchScore
    { totalResearchScoreEngineering :: ResearchScore EngineeringCost
    , totalResearchScoreNatural :: ResearchScore NaturalScienceCost
    , totalResearchScoreSocial :: ResearchScore SocialScienceCost
    deriving (Show, Read, Eq)

Following singleton values are used with ResearchScore and TotalResearchScore to quantify what kind of value we’re talking about.

data EngineeringCost = EngineeringCost
    deriving (Show, Read, Eq)

data NaturalScienceCost = NaturalScienceCost
    deriving (Show, Read, Eq)

data SocialScienceCost = SocialScienceCost
    deriving (Show, Read, Eq)

data ResearchCost = ResearchCost
    deriving (Show, Read, Eq)

data ResearchProduction = ResearchProduction
    deriving (Show, Read, Eq)

data ResearchLeft = ResearchLeft
    deriving (Show, Read, Eq)

Finally there’s Research, which is a record that uses many of the types introduced earlier. It describes what Technology is unlocked upon completion, what’s the cost is and if there are any technologies that have to have been researched before this research can start. The tier of research isn’t currently used for anything, but I have vague plans what to do about it in the future.

data Research = Research
    { researchName :: Text
    , researchType :: Technology
    , researchCategory :: ResearchCategory
    , researchAntecedents :: [Technology]
    , researchCost :: TotalResearchScore ResearchCost
    , researchTier :: ResearchTier
    deriving (Show, Read, Eq)

Tech tree

Putting all this together, we can define a list of Research. Since finding an entry from this list based on research type of it is such a common operation, we also define another data structure for this specific purpose. Map in other programming languages is often known as dictionary, associative array or hash map. It stores key-value - pairs. In our case Technology is used as key and Research as value. We define it based on the list previously defined:

techMap :: Map.Map Technology Research
techMap = Map.fromList $ (\x -> (researchType x, x)) <$> unTechTree techTree

Next time we’ll look into how to actually use all these types and data that were defined.


Subscribe to the comments RSS feed.

Leave Comment

Note to Verbose Commenters
If you can't fit everything you want to say in the comment below then you really should record a response show instead.

Note to Spammers
All comments are moderated. All links are checked by humans. We strip out all html. Feel free to record a show about yourself, or your industry, or any other topic we may find interesting. We also check shows for spam :).

Provide feedback
Your Name/Handle:
Anti Spam Question: What does the letter P in HPR stand for?
Are you a spammer?
What is the HOST_ID for the host of this show?
What does HPR mean to you?