繁体   English   中英

Haskell自定义数据类型

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM