Haskell自定义数据类型
我已经挣扎了好几个小时,而且我弄不明白。Haskell自定义数据类型
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等等。
所以,函数搜索应该检查发送的Word的长度,然后调用search'并发送与列表长度相等的条目列表关联的subList。
一旦进入搜索“我只想对wrd == Word
进行列表的线性搜索,然后返回该单词的def。
任何帮助将是太棒了。
有两个单独的问题:
1.您应该应用def
到Entry
如果你想要一个String
。所以,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
Learn You a Haskell有一个关于模式,如果你想了解更多的匹配部分。它也有一个关于lists and list comprehensions的部分,通常只是一个很好的教程。
但是,我强烈建议不要这样写search'
:这有点不诚实! (例如,作为search'
的调用者,如何区分结果'搜索成功,翻译为“不匹配”,结果'搜索失败'?)
嗯,让我们来看看。你有一个东西的列表,[a]
。您有一些确定搜索是否成功的标准,a -> Bool
。并且您想要在列表中执行搜索,返回元素类型值a
。停止...霍格尔时间!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
作为字段存取器,从Entry
中提取def
。但我们如何将这个应用到Maybe Entry
?
Stop ... 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
,它只是使用默认值。否则,它使用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
如果你不熟悉仿函数,我强烈建议Learn you a Haskell > the Functor typeclass。也许是一个仿函数,这意味着我们可以在值上使用fmap
。
search' :: (Entry -> Bool) -> [Entry] -> Maybe String
search' f es = fmap def $ find f es
为什么我要他们返回[字符串] ...如果我只想要一个完全匹配?而且,如何在代码中添加没有匹配的条件?我的理解是,一旦Haskell发现第一场比赛,它应该停止正在做的并返回...所以我不认为我需要担心多场比赛? – KevinCameron1337
一次提出一个问题。如果你想要一次完全匹配,你必须自己处理其他案例。使用'case'语句,如'[] - >“当没有匹配时要返回的字符串的大小写匹配”; (匹配:_) - >匹配。 2.如果没有匹配,则不需要添加任何附加代码以返回空列表;它已经做到了。你的理解是不正确的。您可能想在任何您最喜欢的教程中查看列表解析部分。 –
我不知道如何使用'case'语句。我会寻找一些例子。并审查列表解析。 – KevinCameron1337