我已经挣扎了几个小时,我无法弄明白。
module Main where
import Data.List
import Data.Function
type Raw = (String, String)
icards = [("the", "le"),("savage", "violent"),("work", "travail"),("wild", "sauvage"),
("chance", "occasion"),("than a", "qu'un"),("expensive.", "cher."),("saves", "en
vaut"),("time", "temps"),("in", "<`a>"), ("worse", "pire"),("{", "{"),("A", "Un"),
("stitch", "point"),("crime;", "crime,"),("a", "une"),("nine.", "cent."),("It's",
"C'est"),("all","tout"),("rare", "rare"),("you", "vous"),("Abandon","Abandonnez"),
("stash", "planquer"),("Everything", "Tout!ce!qui!est"),("who enter.", "qui entrez."),
("Zazie", "Zazie"),("is", "est"),("cat", "chat"),("it's", "c'est"),("raisin", "raisin
sec"),("hope,", "espoir,"),("mistake.", "faute."),("luck", "chance"),("blueberry",
"myrtille"),("I!took", "J'ai pris"),("that", "qui"),("a!chance.", "des risques."),
("drink", "boisson"),("Live", "Vivre"),("regrets.", "regrets."),("stone", "pierre"),
("broke", "a fait d<e'>border"),("without", "sans"),("The!straw", "La goutte d'eau"),
("camel's!back.", "vase.")]
data Entry = Entry {wrd, def :: String, len :: Int, phr :: Bool}
deriving Show
-- English-to-French, hash-table section
entries :: [Entry]
entries = map (\(x, y) -> Entry x y (length x) (' ' `elem` x)) icards
type Run = [Entry]
maxl = maximum [len e | e <- entries]
runs :: [Run]
runs = f 0 $ groupBy ((==) `on` len) $ sortBy (compare `on` len) entries
where f _ [] = []
f i (r @ (Entry {len = l} : _) : rs) | i == l = r : f (i + 1) rs
f i rs = [] : f (i + 1) rs
type Word = String
search' :: Word -> [Entry] -> String
search' searchWord subList
search' _ [] = "unknown"
search' ([def x | x <- subList, (wrd x) == searchWord])==[] = "no match"
search' = [def x | x <- subList, (wrd x) == searchWord]
--search' searchWord subList = (def | x <- subList, (wrd x) == searchWord)
--search' searchWord subList = [def x::String | x <- subList, (wrd x) == searchWord]
--search' searchWord [subList] = [def | x <- subList, (wrd x) == searchWord]
--search' searchWord subList = [def | x <- subList, (wrd x) == searchWord]
--search' searchWord subList = [def x | x <- subList, (wrd x) == searchWord]
--search' searchWord subList = [x->def | x <- subList, (x->wrd) == searchWord]
search :: [Run] -> Word -> String
search runList searchWord = search' searchWord $ runList!!wrdLen
where wrdLen = (length searchWord)
我需要搜索'功能的帮助。 GHCi会告诉我预期的类型是char ...而实际类型是Entry-&gt;字符串。
但我希望type是字符串。我不知道为什么它认为我只想要一个字符。
总的来说,这就是我的期望:
发送[Run]
和Word搜索,其中[Run] = [[Entries]]
和Word = String
[Run]
应格式化,以便[Run]!!0
中的所有条目的长度为0,[Run]!!1
的长度为1等。
因此,函数搜索应检查发送的Word的长度,然后调用search'并将与该列相关的子列表发送给与该单词具有相同长度的条目。
进入搜索后'我只想对wrd == Word
的列表进行线性搜索,然后返回该单词的def。
任何帮助都会很棒。
答案 0 :(得分:4)
有两个不同的问题:
1。如果您需要def
,则应将Entry
应用于String
。因此,search'
的定义应如下所示:
search' searchWord subList = [def x | x <- subList, wrd x == searchWord]
2。先验并不明显,搜索总能找到一个匹配。可能没有比赛或许多比赛。 (我知道你可能希望你提供的数据只会产生一个匹配,但这种推理有点超出了有效和静态的优势。)所以,你的search'
和{{1函数应该返回列表。类型签名应如下所示:
search
...而且,实际上,如果你关闭类型签名,GHC将完全推断出那些类型(最多可以输入同义词)。
编辑:要解决更新后的问题,您可能需要以下内容:
search' :: Word -> [Entry] -> [String]
search :: [Run] -> Word -> [String]
如果您想了解更多,Learn You a Haskell有一个关于模式匹配的部分。它还有lists and list comprehensions部分,通常只是一个很好的教程。
但是,我强烈建议不要这样写search' searchWord subList = case [def x | x <- subList, wrd x == searchWord] of
[] -> "no match"
(match:_) -> match
:这有点不诚实! (例如,作为search'
的调用者,我如何区分结果'搜索成功,翻译是“不匹配”'和结果'搜索失败'?)
答案 1 :(得分:1)
[a]
。您有一些标准可用于确定搜索是否成功,a -> Bool
。并且您希望在列表上执行搜索,返回元素类型a
的值。停止...... Hoogle时间! Hoogling [a] -> (a -> Bool) -> a
,排名最高的是find :: (a -> Bool) -> [a] -> Maybe a
。唯一的问题是它会返回Maybe a
:它会找到Just something
或Nothing
。我说这是适用于search
功能的升级。
search :: [Run] -> Word -> Maybe Entry
search runList searchWord = find (\x -> wrd x == searchWord) $ runList!!wrdLen
where wrdLen = (length searchWord)
由于我们已将search
的合同更改为生成Maybe Entry
而不是简单的String
,因此如果您之前使用此类帐号:
doStuff (search runList searchWord)
您现在必须考虑搜索失败的可能性。
case search runList searchWord of
Just foundWord -> doStuff (def foundWord)
Nothing -> doSomethingElse
如果您完全确定搜索永远不会失败,您可以使用fromJust
doStuff (fromJust $ def $ search runList searchWord)
虽然通常不鼓励使用fromJust
。
现在,还有一件事。您说您只想返回def
,而不是整个Entry
。如您所知,我们可以使用def :: Entry -> String
作为字段访问器从def
中提取Entry
。但是我们如何将其应用于Maybe Entry
?
停止...... Hoogle时间!我们有一个值v :: Maybe a
。我们有一个适用于普通旧a
值的函数f :: a -> b
。我们希望以某种方式将f
应用于v
,从而产生类型b
的结果。 Hoogling Maybe a -> (a -> b) -> b
,我看到两个不错的选择。
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing = n
maybe _ f (Just x) = f x
maybe
函数采用函数和可能的值,还有默认值。如果可能的值结果为Nothing
,则它只使用默认值。否则,它在f
构造函数内部的值上使用函数Just
。
search :: [Run] -> Word -> String
search runList searchWord = search' (\x -> wrd x == searchWord) $ runList!!wrdLen
where wrdLen = (length searchWord)
search' :: (Entry -> Bool) -> [Entry] -> String
search' f es = maybe "not found" def $ find f es
-- or eta reduce: search' = maybe "not found" def . find
这个解决方案没问题,但我更喜欢下一个。
fmap :: Functor f => (a -> b) -> f a -> f b
如果您不熟悉仿函数,我强烈推荐Learn you a Haskell > the Functor typeclass。也许是一个仿函数,这意味着我们可以使用fmap
来表示可能的值。
search' :: (Entry -> Bool) -> [Entry] -> Maybe String
search' f es = fmap def $ find f es