Skip to content

Commit 6e825b1

Browse files
committed
[Haskell] Added Proverb solution
1 parent 5c07e32 commit 6e825b1

File tree

6 files changed

+232
-0
lines changed

6 files changed

+232
-0
lines changed

haskell/proverb/README.md

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
# Proverb
2+
3+
For want of a horseshoe nail, a kingdom was lost, or so the saying goes.
4+
5+
Given a list of inputs, generate the relevant proverb. For example, given the list `["nail", "shoe", "horse", "rider", "message", "battle", "kingdom"]`, you will output the full text of this proverbial rhyme:
6+
7+
```text
8+
For want of a nail the shoe was lost.
9+
For want of a shoe the horse was lost.
10+
For want of a horse the rider was lost.
11+
For want of a rider the message was lost.
12+
For want of a message the battle was lost.
13+
For want of a battle the kingdom was lost.
14+
And all for the want of a nail.
15+
```
16+
17+
Note that the list of inputs may vary; your solution should be able to handle lists of arbitrary length and content. No line of the output text should be a static, unchanging string; all should vary according to the input given.
18+
19+
20+
## Getting Started
21+
22+
Please refer to the [installation](https://exercism.io/tracks/haskell/installation)
23+
and [learning](https://exercism.io/tracks/haskell/learning) help pages.
24+
25+
## Running the tests
26+
27+
To run the test suite, execute the following command:
28+
29+
```bash
30+
stack test
31+
```
32+
33+
#### If you get an error message like this...
34+
35+
```
36+
No .cabal file found in directory
37+
```
38+
39+
You are probably running an old stack version and need
40+
to upgrade it.
41+
42+
#### Otherwise, if you get an error message like this...
43+
44+
```
45+
No compiler found, expected minor version match with...
46+
Try running "stack setup" to install the correct GHC...
47+
```
48+
49+
Just do as it says and it will download and install
50+
the correct compiler version:
51+
52+
```bash
53+
stack setup
54+
```
55+
56+
## Running *GHCi*
57+
58+
If you want to play with your solution in GHCi, just run the command:
59+
60+
```bash
61+
stack ghci
62+
```
63+
64+
## Feedback, Issues, Pull Requests
65+
66+
The [exercism/haskell](https://github.com/exercism/haskell) repository on
67+
GitHub is the home for all of the Haskell exercises.
68+
69+
If you have feedback about an exercise, or want to help implementing a new
70+
one, head over there and create an issue. We'll do our best to help you!
71+
72+
## Source
73+
74+
Wikipedia [http://en.wikipedia.org/wiki/For_Want_of_a_Nail](http://en.wikipedia.org/wiki/For_Want_of_a_Nail)
75+
76+
## Submitting Incomplete Solutions
77+
It's possible to submit an incomplete solution so you can see how others have completed the exercise.

haskell/proverb/package.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
name: proverb
2+
version: 1.1.0.2
3+
4+
dependencies:
5+
- base
6+
7+
library:
8+
exposed-modules: Proverb
9+
source-dirs: src
10+
ghc-options: -Wall
11+
12+
tests:
13+
test:
14+
main: Tests.hs
15+
source-dirs: test
16+
dependencies:
17+
- proverb
18+
- hspec

haskell/proverb/proverb.cabal

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
cabal-version: 1.12
2+
3+
-- This file has been generated from package.yaml by hpack version 0.31.1.
4+
--
5+
-- see: https://github.com/sol/hpack
6+
--
7+
-- hash: 7daafeec8a2dd49fabe794a5696bd6a30f4acc5b1e9a395f632316e692f0fcb8
8+
9+
name: proverb
10+
version: 1.1.0.2
11+
build-type: Simple
12+
13+
library
14+
exposed-modules:
15+
Proverb
16+
other-modules:
17+
Paths_proverb
18+
hs-source-dirs:
19+
src
20+
ghc-options: -Wall
21+
build-depends:
22+
base
23+
default-language: Haskell2010
24+
25+
test-suite test
26+
type: exitcode-stdio-1.0
27+
main-is: Tests.hs
28+
other-modules:
29+
Paths_proverb
30+
hs-source-dirs:
31+
test
32+
build-depends:
33+
base
34+
, hspec
35+
, proverb
36+
default-language: Haskell2010

haskell/proverb/src/Proverb.hs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
module Proverb(recite) where
2+
3+
recite :: [String] -> String
4+
recite [] = ""
5+
recite [item] = reciteConclusion item
6+
recite items = reciteReasoning items ++ reciteConclusion (head items)
7+
8+
9+
reciteReasoning :: [String] -> String
10+
reciteReasoning [] = ""
11+
reciteReasoning [_] = ""
12+
reciteReasoning (item : nextItem : remainingItems) =
13+
"For want of a " ++ item ++ " the " ++ nextItem ++ " was lost.\n"
14+
++ reciteReasoning ([nextItem] ++ remainingItems)
15+
16+
17+
reciteConclusion :: String -> String
18+
reciteConclusion item = "And all for the want of a " ++ item ++ "."

haskell/proverb/stack.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
resolver: lts-14.7

haskell/proverb/test/Tests.hs

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
{-# LANGUAGE RecordWildCards #-}
2+
3+
import Data.Foldable (for_)
4+
import Test.Hspec (Spec, describe, it, shouldBe)
5+
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
6+
import Data.List (intercalate)
7+
8+
import Proverb (recite)
9+
10+
main :: IO ()
11+
main = hspecWith defaultConfig {configFastFail = True} specs
12+
13+
specs :: Spec
14+
specs = describe "recite" $ for_ cases test
15+
where
16+
17+
test Case{..} = it description assertion
18+
where
19+
assertion = recite input `shouldBe` expected
20+
21+
22+
data Case = Case { description :: String
23+
, input :: [String]
24+
, expected :: String
25+
}
26+
27+
joinLines :: [String] -> String
28+
joinLines = intercalate "\n"
29+
30+
cases :: [Case]
31+
cases = [ Case { description = "zero pieces"
32+
, input = []
33+
, expected = ""
34+
}
35+
, Case { description = "one piece"
36+
, input = ["nail"]
37+
, expected = "And all for the want of a nail."
38+
}
39+
, Case { description = "two pieces"
40+
, input = ["nail", "shoe"]
41+
, expected =
42+
joinLines [ "For want of a nail the shoe was lost."
43+
, "And all for the want of a nail."
44+
]
45+
}
46+
, Case { description = "three pieces"
47+
, input = ["nail", "shoe", "horse"]
48+
, expected =
49+
joinLines [ "For want of a nail the shoe was lost."
50+
, "For want of a shoe the horse was lost."
51+
, "And all for the want of a nail."
52+
]
53+
}
54+
, Case { description = "full proverb"
55+
, input = [ "nail"
56+
, "shoe"
57+
, "horse"
58+
, "rider"
59+
, "message"
60+
, "battle"
61+
, "kingdom"
62+
]
63+
, expected =
64+
joinLines [ "For want of a nail the shoe was lost."
65+
, "For want of a shoe the horse was lost."
66+
, "For want of a horse the rider was lost."
67+
, "For want of a rider the message was lost."
68+
, "For want of a message the battle was lost."
69+
, "For want of a battle the kingdom was lost."
70+
, "And all for the want of a nail."
71+
]
72+
}
73+
, Case { description = "four pieces modernized"
74+
, input = ["pin", "gun", "soldier", "battle"]
75+
, expected =
76+
joinLines [ "For want of a pin the gun was lost."
77+
, "For want of a gun the soldier was lost."
78+
, "For want of a soldier the battle was lost."
79+
, "And all for the want of a pin."
80+
]
81+
}
82+
]

0 commit comments

Comments
 (0)