【问题标题】:Applying a function of type String -> [String] -> [String] to two [String]s将 String -> [String] -> [String] 类型的函数应用于两个 [String]
【发布时间】:2015-05-27 22:56:31
【问题描述】:

我很难为此想出一个好的标题。

这里是要点:

我有一个函数 (remIgnored) 打算从字符串列表中删除字符串。

module Main(main) where

import System.Environment
import Data.List
import Data.Char

getLines :: FilePath -> IO [String]
getLines path = do 
    ls <- readFile path
    return (lines ls)

getWords :: [String] -> [String]
getWords ws = words (unlines ws)

remIgnored :: String -> [String] -> [String]
remIgnored _ []                 = []
remIgnored x (y:ys) | x == y    = remIgnored x ys
                    | otherwise = y : remIgnored x ys

main :: IO ()
main = do
    args <- getArgs
    let path = args !! 0
    let ignore = args !! 1
    ig <- getLines ignore
    ls <- getLines path
    let ig'  = map (map toLower) (getWords ig)
    let ls'  = map (map toLower) (getWords ls)
    let ls'' = sort ls'
    putStrLn "Original Lines:\n"
    mapM_ putStrLn ls
    putStrLn "\nLower Cased Words:\n"
    mapM_ putStrLn ls'
    putStrLn "\nLower Cased Words + Sorted:\n"
    mapM_ putStrLn ls''
    putStrLn "\nLower Cased Words + Sorted + Sanitized:\n"
    --Something nice goes here

(请忽略对列表进行细微更改的不断重复,我只是在破解一些东西,看看它们是如何工作的)。

基本上,我的问题是:我将如何将函数 remIgnored 应用于列表 ls'' 以及 ig' 中的每个元素?我整晚都在盯着类型错误,但进展甚微(即使是目前为止的情况也让我很烦恼)。

供参考,我的输入文件:

test.txt:

The quick brown fox jumps over the lazy dog
Peter picked a pail of pickled peppers
She sells sea shells by the sea shore

ignore.txt:

a
the
of
by

样本输出:

Original Lines:
The quick brown fox jumps over the lazy
Peter picked a pail of pickled peppers
She sells sea shells by the sea shore

Lower Cased Words:
the
quick
brown
fox
jumps
over
the
lazy
dog
peter
picked
a
pail
of
pickled
peppers
she
sells
sea
shells
by
the
sea
shore

Lower Cased Words + Sorted:
a
brown
by
dog
fox
jumps
lazy
of
over
pail
peppers
peter
picked
pickled
quick
sea
sea
sells
she
shells
shore
the
the
the

Lower Cased Words + Sorted + Sanitized:

【问题讨论】:

  • @Zeta,代码可以编译。我多次尝试粉碎remIgnoredig ls'' 给我带来了一些搞笑的问题。

标签: string list function haskell types


【解决方案1】:

实际上,您应该使用折叠来做到这一点。

remAllIgnored :: [String] -> [String] -> [String]
remAllIgnored = flip $ foldr remIgnored

是的,就是这么简单。

如果您还不习惯折叠,可以使用忽略列表的递归显式编码:

remAllIgnored [] words = ... -- nothing to ignore means: ?
remAllIgnored (ign0:igns) words
    = let ??  -- somehow you need to 1. apply the `ign0`-ignore-patch
      in ??   --                     2. process the rest of the `igns`

试一试,如果有什么特别的问题,请回来。

【讨论】:

  • 这两个我都不太懂。 remAllIgnored 实际上是如何 的? (在第一种情况下,foldr
  • 它奏效了,但您介意解释一下发生了什么吗?在这个阶段,Haskell 中的一切对我来说都像是黑魔法。
  • 好吧,要理解折叠,您应该实现递归版本,这毕竟是等价的。恐怕你真的必须你自己才能正确理解它。至少尝试一下——你在哪里卡住了?步[]、步1.或步2.
  • @capncoolio 或许foldr 的版本更易于理解,即remAllIgnored toIgnore words = foldr remIgnored words toIgnore。这大致扩展到(remIgnored toIgn1 (... (remIgnored toIgnN words))),其中所有被忽略的单词都从words列表中一一删除。
  • @capncoolio 你以前用过foldr吗?我觉得这张图很好地直观地解释了它的工作原理。 foldr 将其给定的列表(在图像左侧)转换为右侧的嵌套函数调用:commons.wikimedia.org/wiki/File:Right-fold-transformation.png。它用f 调用“替换”列表的:s,用z 替换空列表。左边的列表是写[1,2,3,4,5] 的漫长道路。手写一个小例子会很有帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-29
  • 2016-01-14
  • 1970-01-01
  • 1970-01-01
  • 2013-07-18
  • 2021-09-26
  • 1970-01-01
相关资源
最近更新 更多