[英]Haskell custom data types
我已经为此奋斗了几个小时,但我无法弄清楚。
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-> String。
但是我希望类型是字符串。 我不知道为什么它认为我只想要一个字符。
总的来说,这就是我的期望:发送[Run]
和一个单词进行搜索,其中[Run] = [[Entries]]
和Word = String
[Run]
格式应设置为[Run]!!0
中的所有条目的长度均为0, [Run]!!1
中的所有条目的长度均为1,依此类推。
因此,函数搜索应检查发送的单词的长度,然后调用“搜索”并将其发送给与该单词长度相同的条目列表相关联的subList。
一旦进入搜索,我只想对列表中的wrd == Word
进行线性搜索,然后返回该单词的def。
任何帮助都太棒了。
有两个独立的问题:
1.如果需要String
则应将def
应用于Entry
。 因此,“ search'
的定义应如下所示:
search' searchWord subList = [def x | x <- subList, wrd x == searchWord]
2.显然,先验并不总是总是找到一个匹配项。 可能没有匹配项,或者有很多匹配项。 (我知道您可能希望您提供的数据会完全匹配,但是这种推理超出了可以有效和静态地完成的范围。)因此,您的search'
和search
功能应返回列表。 类型签名应如下所示:
search' :: Word -> [Entry] -> [String]
search :: [Run] -> Word -> [String]
……的确,如果您保留类型签名,GHC会准确推断出这些类型(最多为类型同义词)。
编辑:要解决更新的问题,您可能需要这样的东西:
search' searchWord subList = case [def x | x <- subList, wrd x == searchWord] of
[] -> "no match"
(match:_) -> match
了解您如果您想了解更多信息, Haskell会提供有关模式匹配的部分。 它还有一个关于列表和列表理解的部分 ,通常只是一个很好的教程。
但是,我强烈建议您不要这样写search'
:这有点不诚实! (例如,作为search'
的调用方search'
,如何区分结果“搜索成功,翻译为“不匹配””和结果“搜索失败”?)
嗯,让我们看看。 您有一个东西列表, [a]
。 您有一些条件来确定搜索是否成功, a -> Bool
。 您想在列表上执行搜索,返回元素类型a
a的值。 停下来...安静的时间! Hoogling [a] -> (a -> Bool) -> a
a- [a] -> (a -> Bool) -> a
,最热门的是find :: (a -> Bool) -> [a] -> Maybe a
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
作为字段访问器从Entry
提取def
。 但是我们如何将其应用于Maybe Entry
?
停下来...安静的时间! 我们有一个值v :: Maybe a
。 我们有一个对普通旧的a
值起作用的函数f :: a -> b
。 我们想以某种方式将f
应用于v
,从而产生类型b
的结果。 Hoogling Maybe a -> (a -> b) -> b
a- Maybe a -> (a -> b) -> b
,我看到两个不错的选择。
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n _ Nothing = n
maybe _ f (Just x) = f x
maybe
函数接受一个函数和一个maybe值,以及一个default 。 如果maybe值变成Nothing
,则仅使用默认值。 否则,它将对Just
构造函数内部的值使用函数f
。
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
如果您不熟悉函子,我强烈建议您学习Haskell>函子类型类 。 也许是一个函子,这意味着我们可以对可能的值使用fmap
。
search' :: (Entry -> Bool) -> [Entry] -> Maybe String
search' f es = fmap def $ find f es
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.