Проверьте каждый символ строки со стражами [Haskell] - PullRequest
0 голосов
/ 04 марта 2020

У меня проблема, когда я пытаюсь использовать Haskell. Я хочу прочитать строку чисел и распечатать различные сообщения, когда я вижу символы.

import System.Environment
import System.Exit
import Data.List
import Control.Monad


test_parse:: [Char] -> IO ()
test_parse [] = putStrLn "\n"
test_parse (a:b:c:xs)
            | a == '1' && b == '2' && c == '3' = putStrLn ("True")
            | a == '2' && b == '3' && c == '4' = putStrLn ("False")
            | a == '4' && b == '5' && c == '6' = putStrLn ("maybe")
            | otherwise = test_parse (b:c:xs)

main = do
    let numbers = "123456"
    let loop = do
            goGlenn <- getLine
            test_parse numbers
            putStrLn goGlenn
            when (goGlenn /= "start") loop
    loop
    putStrLn "ok"

Проблема заключается в следующем. Я хотел бы напечатать "True \ nFalse \ nMaybe \ n", но я печатаю только "True \ n". Я знаю, что моя проблема в том, что когда охранники совершают какое-либо действие, оно покидает функцию. Но я не вижу, как проверить всю строку, не оставляя 'test_parse.

Если у кого-нибудь есть идея, спасибо.

Ответы [ 2 ]

5 голосов
/ 04 марта 2020

Вы хотите проверить каждый суффикс, независимо от результата в префиксе. Один пример:

-- output a string based on the first 3 characters of the input
classify :: String -> IO ()
classify xs = case take 3 xs of
                "123" -> putStrLn "True"
                "234" -> putStrLn "False"
                "456" -> putStrLn "maybe"
                otherwise -> return ()

-- call classify repeatedly on different suffixes of the input
test_parse :: String -> IO ()
test_parse [] = return ()
test_parse all@(_:xs) = do
    classify all
    test_parse xs
0 голосов
/ 04 марта 2020

Чтобы проиллюстрировать мнение Чепнера о classify, верните список String с вместо ввода-вывода:

import Data.List (tails)

classify :: String -> [String]
classify s = case take 3 s of
  "123" -> return "True"
  "234" -> return "False"
  "456" -> return "maybe"
  otherwise -> mempty

classifyAll :: String -> [String]
classifyAll s = tails s >>= classify

main :: IO ()
main = interact (unlines . classifyAll)

Выполнение этого,

$ stack ghc classify.hs
$ echo 123456 | ./classify
True
False
maybe

Я не могу выбрать, хочу ли я ставить \ n после печати или нет.

В принципе, это работает, но мы можем удалить \ n, если захотим?

Если вы хотите отделить что-то, отличное от перевода строки,

import Data.List (intercalate, tails)

...

main :: IO ()
main = interact ((++ "\n") . intercalate ", " . classifyAll)

Запустив это,

$ echo 123456 | ./classify
True, False, maybe

Разделение кода, который анализирует и печатает, также делает ваш код более легко тестируемым. Например,

spec_classify :: Spec
spec_classify =
  describe "classify" $
    it "classifies 123, 234 and 456" $
      classifyAll "123456" `shouldBe` ["True", "False", "maybe"]

Проверка этого

$ stack ghci classify.hs
> hspec spec_classify 

classify
  classifies 123, 234 and 456

Finished in 0.0005 seconds
1 example, 0 failures
...