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

# BuilderNamedBob's solution

## to Raindrops in the Haskell Track

Published at Apr 20 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 = if or hasFactorList
then concat [stringList !! x | x <- [0..2], hasFactorList !! x]
else show n
where
hasFactorList = hasFactors [3,5,7] n
stringList = ["Pling","Plang","Plong"]

hasFactor :: Int -> Int -> Bool
hasFactor factor number = number `mod` factor == 0

hasFactors :: [Int] -> Int -> [Bool]
hasFactors factorList number = map (`hasFactor` number) factorList``````

### What can you learn from this solution?

A huge amount can be learned from reading other peopleâ€™s code. This is why we wanted to give exercism users the option of making their solutions public.

Here are some questions to help you reflect on this solution and learn the most from it.

• What compromises have been made?