Background
This problem comes courtesy of the great folks over at Exercism. I highly recommend jumping on their Haskell track to apply your knowledge of Haskell.
The Problem
Given an age in seconds, calculate how old someone would be on:
- Mercury: orbital period 0.2408467 Earth years
- Venus: orbital period 0.61519726 Earth years
- Earth: orbital period 1.0 Earth years, 365.25 Earth days, or 31557600 seconds
- 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.
Knowledge You Need to Solve This Problem
- Basic Functions and How to Write Them
- Monads
- Pattern Matching
The Solution
To solve this problem, we’ll complete the ageOn
function, which will calculate the age on a given planet based on the age in seconds. We’ll use the starting Planet
data type and calculate the age using each planet’s orbital period relative to Earth years.
Steps to Solution
- Define Earth’s Orbital Period in Seconds:
- Use
31557600
seconds for one Earth year, as specified in the instructions.
- Use
- Define Each Planet’s Orbital Period Relative to Earth:
- Each planet has a different orbital period in Earth years, which we’ll use to scale the age.
- Implement
ageOn
Function:ageOn
takes a planet and an age in seconds.- Convert the age in seconds to Earth years.
- Adjust for each planet by dividing by the planet’s orbital period.
Haskell Code
Here’s the completed Haskell code:
-- Define the Planet data type
data Planet = Mercury
| Venus
| Earth
| Mars
| Jupiter
| Saturn
| Uranus
| Neptune
-- Earth's orbital period in seconds
earthYearInSeconds :: Float
earthYearInSeconds = 31557600
-- Function to get the orbital period of each planet in Earth years
orbitalPeriod :: Planet -> Float
orbitalPeriod Mercury = 0.2408467
orbitalPeriod Venus = 0.61519726
orbitalPeriod Earth = 1.0
orbitalPeriod Mars = 1.8808158
orbitalPeriod Jupiter = 11.862615
orbitalPeriod Saturn = 29.447498
orbitalPeriod Uranus = 84.016846
orbitalPeriod Neptune = 164.79132
-- Calculate the age on a given planet based on the age in seconds
ageOn :: Planet -> Float -> Float
ageOn planet seconds = seconds / (earthYearInSeconds * orbitalPeriod planet)
-- Usage example: Calculate age on Earth for someone who is 1,000,000,000 seconds old
main :: IO ()
main = do
let ageInSeconds = 1000000000
print $ ageOn Earth ageInSeconds
-- Should output approximately 31.69
print $ ageOn Mercury ageInSeconds
-- Calculate age on other planets if needed
print $ ageOn Venus ageInSeconds
print $ ageOn Mars ageInSeconds
print $ ageOn Jupiter ageInSeconds
print $ ageOn Saturn ageInSeconds
print $ ageOn Uranus ageInSeconds
print $ ageOn Neptune ageInSeconds
Explanation
earthYearInSeconds
:- Defines the number of seconds in one Earth year.
orbitalPeriod
:- Matches each
Planet
value to its orbital period in Earth years. This function is key to adjusting for the different year lengths on each planet.
- Matches each
ageOn
:- Converts
seconds
to Earth years by dividing byearthYearInSeconds
. - Then it divides by the orbital period of the given planet (using
orbitalPeriod planet
) to get the age on that planet.
- Converts
Example Usage
When running the main
function, you should see output like this:
31.69 -- Earth
131.57 -- Mercury
51.51 -- Venus
16.85 -- Mars
2.67 -- Jupiter
1.08 -- Saturn
0.38 -- Uranus
0.19 -- Neptune
Each number represents the age in years for someone who is 1,000,000,000 seconds old on each planet.
💡 Helpful References
Exercism - Space Age
https://exercism.org/tracks/haskell/exercises/space-age/
Leave a Reply