ðŸŽ‰ Exercism Research is now launched. Help Exercism, help science and have some fun at research.exercism.io ðŸŽ‰

# airclovis's solution

## to Raindrops in the Haskell Track

Published at Apr 11 2021 · 0 comments
Instructions
Test suite
Solution

Your task is to convert a number into a string that contains raindrop sounds corresponding to certain potential factors. A factor is a number that evenly divides into another number, leaving no remainder. The simplest way to test if a one number is a factor of another is to use the modulo operation.

The rules of `raindrops` are that if a given number:

• has 3 as a factor, add 'Pling' to the result.
• has 5 as a factor, add 'Plang' to the result.
• has 7 as a factor, add 'Plong' to the result.
• does not have any of 3, 5, or 7 as a factor, the result should be the digits of the number.

## Examples

• 28 has 7 as a factor, but not 3 or 5, so the result would be "Plong".
• 30 has both 3 and 5 as factors, but not 7, so the result would be "PlingPlang".
• 34 is not factored by 3, 5, or 7, so the result would be "34".

## Hints

You need to implement the `convert` function that returns number converted to raindrop sound. You can use the provided signature if you are unsure about the types, but don't let it restrict your creativity:

``````convert :: Int -> String
``````

This exercise works with textual data. For historical reasons, Haskell's `String` type is synonymous with `[Char]`, a list of characters. For more efficient handling of textual data, the `Text` type can be used.

As an optional extension to this exercise, you can

• Add `- text` to your list of dependencies in package.yaml.
• Import `Data.Text` in the following way:
``````import qualified Data.Text as T
import           Data.Text (Text)
``````
• You can now write e.g. `convert :: Int -> Text` and refer to `Data.Text` combinators as e.g. `T.pack`.
• Look up the documentation for `Data.Text`,
• You can then replace all occurrences of `String` with `Text` in Raindrops.hs:
``````convert :: Int -> Text
``````

This part is entirely optional.

## Getting Started

Please refer to the installation and learning help pages.

## 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

A variation on FizzBuzz, a famous technical interview question that is intended to weed out potential candidates. That question is itself derived from Fizz Buzz, a popular children's game for teaching division. https://en.wikipedia.org/wiki/Fizz_buzz

## 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 #-}

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

import Raindrops (convert)

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

specs :: Spec
specs = describe "convert" \$ for_ cases test
where

test (number, expected) = it description assertion
where
description = show number
assertion   = convert number `shouldBe` fromString expected

cases = [ (   1, "1"              )
, (   3, "Pling"          )
, (   5, "Plang"          )
, (   7, "Plong"          )
, (   6, "Pling"          )
, (   8, "8"              )
, (   9, "Pling"          )
, (  10, "Plang"          )
, (  14, "Plong"          )
, (  15, "PlingPlang"     )
, (  21, "PlingPlong"     )
, (  25, "Plang"          )
, (  27, "Pling"          )
, (  35, "PlangPlong"     )
, (  49, "Plong"          )
, (  52, "52"             )
, ( 105, "PlingPlangPlong")
, (3125, "Plang"          ) ]

-- 4d356f447fcddd28b5dbf1df881bed95f26bba85``````
``````module Raindrops (convert) where

convert :: Int -> String
convert n =
let raindrops = pling ++ plang ++ plong
in
if null raindrops then show n else raindrops
where
pling = if n `mod` 3 == 0 then "Pling" else ""
plang = if n `mod` 5 == 0 then "Plang" else ""
plong = if n `mod` 7 == 0 then "Plong" else ""``````