✅ haskell: bob
This commit is contained in:
parent
b1e69d7da9
commit
46ae029958
88
haskell/bob/HELP.md
Normal file
88
haskell/bob/HELP.md
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Help
|
||||||
|
|
||||||
|
## Running the tests
|
||||||
|
|
||||||
|
To run the test suite, execute the following command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
stack test
|
||||||
|
```
|
||||||
|
|
||||||
|
#### If you get an error message like this...
|
||||||
|
|
||||||
|
```
|
||||||
|
No .cabal file found in directory
|
||||||
|
```
|
||||||
|
|
||||||
|
or
|
||||||
|
|
||||||
|
```
|
||||||
|
RedownloadInvalidResponse Request {
|
||||||
|
...
|
||||||
|
}
|
||||||
|
"/home/username/.stack/build-plan/lts-xx.yy.yaml" (Response {responseStatus = Status {statusCode = 404, statusMessage = "Not Found"},
|
||||||
|
```
|
||||||
|
|
||||||
|
You are probably running an old stack version and need
|
||||||
|
to upgrade it. Try running:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
stack upgrade
|
||||||
|
```
|
||||||
|
|
||||||
|
Or see other options for upgrading at [Stack documentation](https://docs.haskellstack.org/en/stable/install_and_upgrade/#upgrade).
|
||||||
|
|
||||||
|
#### 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:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
stack setup
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
If you want to play with your solution in GHCi, just run the command:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
stack ghci
|
||||||
|
```
|
||||||
|
|
||||||
|
## Submitting your solution
|
||||||
|
|
||||||
|
You can submit your solution using the `exercism submit src/Bob.hs` command.
|
||||||
|
This command will upload your solution to the Exercism website and print the solution page's URL.
|
||||||
|
|
||||||
|
It's possible to submit an incomplete solution which allows you to:
|
||||||
|
|
||||||
|
- See how others have completed the exercise
|
||||||
|
- Request help from a mentor
|
||||||
|
|
||||||
|
## Need to get help?
|
||||||
|
|
||||||
|
If you'd like help solving the exercise, check the following pages:
|
||||||
|
|
||||||
|
- The [Haskell track's documentation](https://exercism.org/docs/tracks/haskell)
|
||||||
|
- [Exercism's support channel on gitter](https://gitter.im/exercism/support)
|
||||||
|
- The [Frequently Asked Questions](https://exercism.org/docs/using/faqs)
|
||||||
|
|
||||||
|
Should those resources not suffice, you could submit your (incomplete) solution to request mentoring.
|
||||||
|
|
||||||
|
## Getting Started
|
||||||
|
|
||||||
|
Please refer to the [installation](https://exercism.io/tracks/haskell/installation)
|
||||||
|
and [learning](https://exercism.io/tracks/haskell/learning) help pages.
|
||||||
|
|
||||||
|
## Feedback, Issues, Pull Requests
|
||||||
|
|
||||||
|
The [exercism/haskell](https://github.com/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!
|
||||||
|
{{ with .Spec.Credits }}
|
88
haskell/bob/README.md
Normal file
88
haskell/bob/README.md
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
# Bob
|
||||||
|
|
||||||
|
Welcome to Bob on Exercism's Haskell Track.
|
||||||
|
If you need help running the tests or submitting your code, check out `HELP.md`.
|
||||||
|
|
||||||
|
## Instructions
|
||||||
|
|
||||||
|
Bob is a lackadaisical teenager. In conversation, his responses are very limited.
|
||||||
|
|
||||||
|
Bob answers 'Sure.' if you ask him a question, such as "How are you?".
|
||||||
|
|
||||||
|
He answers 'Whoa, chill out!' if you YELL AT HIM (in all capitals).
|
||||||
|
|
||||||
|
He answers 'Calm down, I know what I'm doing!' if you yell a question at him.
|
||||||
|
|
||||||
|
He says 'Fine. Be that way!' if you address him without actually saying
|
||||||
|
anything.
|
||||||
|
|
||||||
|
He answers 'Whatever.' to anything else.
|
||||||
|
|
||||||
|
Bob's conversational partner is a purist when it comes to written communication and always follows normal rules regarding sentence punctuation in English.
|
||||||
|
|
||||||
|
You need to implement the `responseFor` function that returns Bob's response
|
||||||
|
for a given input. You can use the provided signature if you are unsure
|
||||||
|
about the types, but don't let it restrict your creativity:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
responseFor :: String -> String
|
||||||
|
```
|
||||||
|
|
||||||
|
To solve this exercise you may read up on:
|
||||||
|
|
||||||
|
- [Guards][guards]
|
||||||
|
|
||||||
|
[guards]: https://www.futurelearn.com/courses/functional-programming-haskell/0/steps/27226
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
- Read about [string types](https://haskell-lang.org/tutorial/string-types) in Haskell.
|
||||||
|
- Add `- text` to your list of dependencies in package.yaml.
|
||||||
|
- Import `Data.Text` in [the following way](https://hackernoon.com/4-steps-to-a-better-imports-list-in-haskell-43a3d868273c):
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Data.Text (Text)
|
||||||
|
```
|
||||||
|
|
||||||
|
- You can now write e.g. `responseFor :: Text -> Text` and refer to `Data.Text` combinators as e.g. `T.isSuffixOf`.
|
||||||
|
- Look up the documentation for [`Data.Text`](https://hackage.haskell.org/package/text/docs/Data-Text.html),
|
||||||
|
- You can then replace all occurrences of `String` with `Text` in Bob.hs:
|
||||||
|
|
||||||
|
```haskell
|
||||||
|
responseFor :: Text -> Text
|
||||||
|
```
|
||||||
|
|
||||||
|
This part is entirely optional.
|
||||||
|
|
||||||
|
## Source
|
||||||
|
|
||||||
|
### Created by
|
||||||
|
|
||||||
|
- @etrepum
|
||||||
|
|
||||||
|
### Contributed to by
|
||||||
|
|
||||||
|
- @austinlyons
|
||||||
|
- @cmccandless
|
||||||
|
- @danbst
|
||||||
|
- @eijynagai
|
||||||
|
- @hritchie
|
||||||
|
- @iHiD
|
||||||
|
- @jrib
|
||||||
|
- @Kobata
|
||||||
|
- @kytrinyx
|
||||||
|
- @petertseng
|
||||||
|
- @ppartarr
|
||||||
|
- @rbasso
|
||||||
|
- @sshine
|
||||||
|
- @tejasbubane
|
||||||
|
- @tofische
|
||||||
|
|
||||||
|
### Based on
|
||||||
|
|
||||||
|
Inspired by the 'Deaf Grandma' exercise in Chris Pine's Learn to Program tutorial. - http://pine.fm/LearnToProgram/?Chapter=06
|
17
haskell/bob/examples/success-standard/package.yaml
Normal file
17
haskell/bob/examples/success-standard/package.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: bob
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base
|
||||||
|
- safe
|
||||||
|
|
||||||
|
library:
|
||||||
|
exposed-modules: Bob
|
||||||
|
source-dirs: src
|
||||||
|
|
||||||
|
tests:
|
||||||
|
test:
|
||||||
|
main: Tests.hs
|
||||||
|
source-dirs: test
|
||||||
|
dependencies:
|
||||||
|
- bob
|
||||||
|
- hspec
|
17
haskell/bob/examples/success-text/package.yaml
Normal file
17
haskell/bob/examples/success-text/package.yaml
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
name: bob
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base
|
||||||
|
- text
|
||||||
|
|
||||||
|
library:
|
||||||
|
exposed-modules: Bob
|
||||||
|
source-dirs: src
|
||||||
|
|
||||||
|
tests:
|
||||||
|
test:
|
||||||
|
main: Tests.hs
|
||||||
|
source-dirs: test
|
||||||
|
dependencies:
|
||||||
|
- bob
|
||||||
|
- hspec
|
19
haskell/bob/examples/success-text/src/Bob.hs
Normal file
19
haskell/bob/examples/success-text/src/Bob.hs
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
module Bob (responseFor) where
|
||||||
|
|
||||||
|
import Data.Char (isSpace, isUpper, isLower)
|
||||||
|
import qualified Data.Text as T
|
||||||
|
import Data.Text (Text)
|
||||||
|
|
||||||
|
responseFor :: Text -> Text
|
||||||
|
responseFor s
|
||||||
|
| isSilent s = "Fine. Be that way!"
|
||||||
|
| isYelling s && isAsking s = "Calm down, I know what I'm doing!"
|
||||||
|
| isYelling s = "Whoa, chill out!"
|
||||||
|
| isAsking s = "Sure."
|
||||||
|
| otherwise = "Whatever."
|
||||||
|
|
||||||
|
isSilent, isYelling, isAsking :: Text -> Bool
|
||||||
|
isSilent = T.all isSpace
|
||||||
|
isYelling = (&&) <$> T.any isUpper <*> T.all (not . isLower)
|
||||||
|
isAsking = (Just '?' ==) . fmap snd . T.unsnoc . T.stripEnd
|
21
haskell/bob/package.yaml
Normal file
21
haskell/bob/package.yaml
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
name: bob
|
||||||
|
version: 1.4.0.10
|
||||||
|
|
||||||
|
dependencies:
|
||||||
|
- base
|
||||||
|
|
||||||
|
library:
|
||||||
|
exposed-modules: Bob
|
||||||
|
source-dirs: src
|
||||||
|
ghc-options: -Wall
|
||||||
|
# dependencies:
|
||||||
|
# - foo # List here the packages you
|
||||||
|
# - bar # want to use in your solution.
|
||||||
|
|
||||||
|
tests:
|
||||||
|
test:
|
||||||
|
main: Tests.hs
|
||||||
|
source-dirs: test
|
||||||
|
dependencies:
|
||||||
|
- bob
|
||||||
|
- hspec
|
21
haskell/bob/src/Bob.hs
Normal file
21
haskell/bob/src/Bob.hs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
module Bob (responseFor) where
|
||||||
|
|
||||||
|
import Data.Char (isLower, isSpace, isUpper)
|
||||||
|
import Data.List (dropWhileEnd)
|
||||||
|
|
||||||
|
responseFor :: String -> String
|
||||||
|
responseFor xs
|
||||||
|
| isSilent xs = "Fine. Be that way!"
|
||||||
|
| isQuestion xs && isYelling xs = "Calm down, I know what I'm doing!"
|
||||||
|
| isQuestion xs = "Sure."
|
||||||
|
| isYelling xs = "Whoa, chill out!"
|
||||||
|
| otherwise = "Whatever."
|
||||||
|
|
||||||
|
isQuestion :: String -> Bool
|
||||||
|
isQuestion s = (last (dropWhileEnd isSpace s)) == '?'
|
||||||
|
|
||||||
|
isYelling :: String -> Bool
|
||||||
|
isYelling s = (any isUpper s) && not (any isLower s)
|
||||||
|
|
||||||
|
isSilent :: String -> Bool
|
||||||
|
isSilent = all isSpace
|
1
haskell/bob/stack.yaml
Normal file
1
haskell/bob/stack.yaml
Normal file
@ -0,0 +1 @@
|
|||||||
|
resolver: lts-16.21
|
127
haskell/bob/test/Tests.hs
Normal file
127
haskell/bob/test/Tests.hs
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
|
||||||
|
import Data.Foldable (for_)
|
||||||
|
import Test.Hspec (Spec, describe, it, shouldBe)
|
||||||
|
import Test.Hspec.Runner (configFastFail, defaultConfig, hspecWith)
|
||||||
|
import Data.String (fromString)
|
||||||
|
|
||||||
|
import Bob (responseFor)
|
||||||
|
|
||||||
|
main :: IO ()
|
||||||
|
main = hspecWith defaultConfig {configFastFail = True} specs
|
||||||
|
|
||||||
|
specs :: Spec
|
||||||
|
specs = describe "responseFor" $ for_ cases test
|
||||||
|
where
|
||||||
|
test Case{..} = it description $ responseFor (fromString input) `shouldBe` fromString expected
|
||||||
|
|
||||||
|
data Case = Case { description :: String
|
||||||
|
, input :: String
|
||||||
|
, expected :: String
|
||||||
|
}
|
||||||
|
|
||||||
|
cases :: [Case]
|
||||||
|
cases = [ Case { description = "stating something"
|
||||||
|
, input = "Tom-ay-to, tom-aaaah-to."
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "shouting"
|
||||||
|
, input = "WATCH OUT!"
|
||||||
|
, expected = "Whoa, chill out!"
|
||||||
|
}
|
||||||
|
, Case { description = "shouting gibberish"
|
||||||
|
, input = "FCECDFCAAB"
|
||||||
|
, expected = "Whoa, chill out!"
|
||||||
|
}
|
||||||
|
, Case { description = "asking a question"
|
||||||
|
, input = "Does this cryogenic chamber make me look fat?"
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "asking a numeric question"
|
||||||
|
, input = "You are, what, like 15?"
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "asking gibberish"
|
||||||
|
, input = "fffbbcbeab?"
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "talking forcefully"
|
||||||
|
, input = "Let's go make out behind the gym!"
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "using acronyms in regular speech"
|
||||||
|
, input = "It's OK if you don't want to go to the DMV."
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "forceful question"
|
||||||
|
, input = "WHAT THE HELL WERE YOU THINKING?"
|
||||||
|
, expected = "Calm down, I know what I'm doing!"
|
||||||
|
}
|
||||||
|
, Case { description = "shouting numbers"
|
||||||
|
, input = "1, 2, 3 GO!"
|
||||||
|
, expected = "Whoa, chill out!"
|
||||||
|
}
|
||||||
|
, Case { description = "only numbers"
|
||||||
|
, input = "1, 2, 3"
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "question with only numbers"
|
||||||
|
, input = "4?"
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "shouting with special characters"
|
||||||
|
, input = "ZOMG THE %^*@#$(*^ ZOMBIES ARE COMING!!11!!1!"
|
||||||
|
, expected = "Whoa, chill out!"
|
||||||
|
}
|
||||||
|
, Case { description = "shouting with no exclamation mark"
|
||||||
|
, input = "I HATE THE DMV"
|
||||||
|
, expected = "Whoa, chill out!"
|
||||||
|
}
|
||||||
|
, Case { description = "statement containing question mark"
|
||||||
|
, input = "Ending with ? means a question."
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "non-letters with question"
|
||||||
|
, input = ":) ?"
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "prattling on"
|
||||||
|
, input = "Wait! Hang on. Are you going to be OK?"
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "silence"
|
||||||
|
, input = ""
|
||||||
|
, expected = "Fine. Be that way!"
|
||||||
|
}
|
||||||
|
, Case { description = "prolonged silence"
|
||||||
|
, input = " "
|
||||||
|
, expected = "Fine. Be that way!"
|
||||||
|
}
|
||||||
|
, Case { description = "alternate silence"
|
||||||
|
, input = "\t\t\t\t\t\t\t\t\t\t"
|
||||||
|
, expected = "Fine. Be that way!"
|
||||||
|
}
|
||||||
|
, Case { description = "multiple line question"
|
||||||
|
, input = "\nDoes this cryogenic chamber make me look fat?\nNo."
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "starting with whitespace"
|
||||||
|
, input = " hmmmmmmm..."
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
, Case { description = "ending with whitespace"
|
||||||
|
, input = "Okay if like my spacebar quite a bit? "
|
||||||
|
, expected = "Sure."
|
||||||
|
}
|
||||||
|
, Case { description = "other whitespace"
|
||||||
|
, input = "\n\r \t"
|
||||||
|
, expected = "Fine. Be that way!"
|
||||||
|
}
|
||||||
|
, Case { description = "non-question ending with whitespace"
|
||||||
|
, input = "This is a statement ending with whitespace "
|
||||||
|
, expected = "Whatever."
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
-- a0b1123b94254a9db443a84a612b51cc3f3ed537
|
Loading…
x
Reference in New Issue
Block a user