 # murdho's solution

## to Space Age in the Haskell Track

Published at Jul 29 2018 · 0 comments
Instructions
Test suite
Solution

#### Note:

This exercise has changed since this solution was written.

Given an age in seconds, calculate how old someone would be on:

• Earth: orbital period 365.25 Earth days, or 31557600 seconds
• Mercury: orbital period 0.2408467 Earth years
• Venus: orbital period 0.61519726 Earth years
• Mars: orbital period 1.8808158 Earth years
• Jupiter: orbital period 11.862615 Earth years
• Saturn: orbital period 29.447498 Earth years
• Uranus: orbital period 84.016846 Earth years
• Neptune: orbital period 164.79132 Earth years

So if you were told someone were 1,000,000,000 seconds old, you should be able to say that they're 31.69 Earth-years old.

If you're wondering why Pluto didn't make the cut, go watch this youtube video.

## Hints

In this exercise, we provided the definition of the algebric data type named `Planet`. You need to implement the `ageOn` function, that calculates how many years old someone would be on a `Planet`, given an age in seconds.

Your can use the provided signature if you are unsure about the types, but don't let it restrict your creativity:

``````ageOn :: Planet -> Float -> Float
``````

## Getting Started

For installation and learning resources, refer to the exercism help page.

## Running the tests

To run the test suite, execute the following command:

``````stack test
``````

#### If you get an error message like this...

``````No .cabal file found in directory
``````

You are probably running an old stack version and need to upgrade it.

#### Otherwise, if you get an error message like this...

``````No compiler found, expected minor version match with...
Try running "stack setup" to install the correct GHC...
``````

Just do as it says and it will download and install the correct compiler version:

``````stack setup
``````

## Running GHCi

If you want to play with your solution in GHCi, just run the command:

``````stack ghci
``````

## Feedback, Issues, Pull Requests

The exercism/haskell repository on GitHub is the home for all of the Haskell exercises.

If you have feedback about an exercise, or want to help implementing a new one, head over there and create an issue. We'll do our best to help you!

## Source

Partially inspired by Chapter 1 in Chris Pine's online Learn to Program tutorial. http://pine.fm/LearnToProgram/?Chapter=01

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### Tests.hs

``````{-# OPTIONS_GHC -fno-warn-type-defaults #-}
{-# LANGUAGE RecordWildCards #-}

import Data.Foldable     (for_)
import Data.Function     (on)
import Test.Hspec        (Spec, describe, it, shouldBe)
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)

import SpaceAge (Planet(..), ageOn)

main :: IO ()
main = hspecWith defaultConfig {configFastFail = True} specs

specs :: Spec
specs = describe "ageOn" \$ for_ cases test
where
-- Here we used `fromIntegral`, `fromRational` and `toRational` to
-- generalize the test suite, allowing any function that takes a
-- `Planet` and a number, returning an instance of `Real`.
test Case{..} = it description \$ expression `shouldBeAround` expected
where
expression = fromRational
. toRational
. ageOn planet
. fromIntegral
\$ seconds
shouldBeAround = shouldBe `on` roundTo 2
roundTo n = (/ 10 ^ n) . fromIntegral . round . (* 10 ^ n)

data Case = Case { description :: String
, planet      :: Planet
, seconds     :: Integer
, expected    :: Double
}

cases :: [Case]
cases = [ Case { description = "Earth"
, planet      = Earth
, seconds     = 1000000000
, expected    = 31.69
}
, Case { description = "Mercury"
, planet      = Mercury
, seconds     = 2134835688
, expected    = 280.88
}
, Case { description = "Venus"
, planet      = Venus
, seconds     = 189839836
, expected    = 9.78
}
, Case { description = "Mars"
, planet      = Mars
, seconds     = 2329871239
, expected    = 39.25
}
, Case { description = "Jupiter"
, planet      = Jupiter
, seconds     = 901876382
, expected    = 2.41
}
, Case { description = "Saturn"
, planet      = Saturn
, seconds     = 3000000000
, expected    = 3.23
}
, Case { description = "Uranus"
, planet      = Uranus
, seconds     = 3210123456
, expected    = 1.21
}
, Case { description = "Neptune"
, planet      = Neptune
, seconds     = 8210123456
, expected    = 1.58
}
]``````
``````module SpaceAge (Planet(..), ageOn) where

data Planet = Mercury
| Venus
| Earth
| Mars
| Jupiter
| Saturn
| Uranus
| Neptune

ageOn :: Fractional a => Planet -> a -> a
ageOn planet seconds = seconds / (earthYearInSeconds * orbitalPeriodInEarthYears planet)

earthYearInSeconds :: Fractional a => a
earthYearInSeconds = 31557600

orbitalPeriodInEarthYears :: Fractional a => Planet -> a
orbitalPeriodInEarthYears Mercury = 0.2408467
orbitalPeriodInEarthYears Venus   = 0.61519726
orbitalPeriodInEarthYears Earth   = 1
orbitalPeriodInEarthYears Mars    = 1.8808158
orbitalPeriodInEarthYears Jupiter = 11.862615
orbitalPeriodInEarthYears Saturn  = 29.447498
orbitalPeriodInEarthYears Uranus  = 84.016846
orbitalPeriodInEarthYears Neptune = 164.79132``````