【问题标题】:Haskell custom data typesHaskell 自定义数据类型
【发布时间】:2011-12-20 13:10:58
【问题描述】:

我已经为此苦苦挣扎了好几个小时,但我无法弄清楚。

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。

但我希望 type 是字符串。我不知道为什么它认为我只想要一个字符。

总的来说,这是我所期望的: 发送 [Run] 和要搜索的单词,其中 [Run] = [[Entries]]Word = String

[Run] 应该被格式化,所以[Run]!!0 中的所有条目的长度都是 0,[Run]!!1 的长度是 1 等等。

因此,函数 search 应该检查发送的 Word 的长度,然后调用 search' 并将 subList 发送给与该单词长度相同的条目列表相关联。

一旦内部搜索'我只想对wrd == Word 的列表进行线性搜索,然后返回该单词的定义。

任何帮助都会很棒。

【问题讨论】:

    标签: haskell hash types


    【解决方案1】:

    有两个不同的问题:

    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
    

    Learn You a Haskell 有一个关于模式匹配的部分,如果你想了解更多。它还有一个关于lists and list comprehensions 的部分,通常只是一个很好的教程。

    但是,我强烈建议不要这样写search':这有点不诚实! (例如,作为search'的调用者,如何区分结果“搜索成功,翻译为“不匹配””和结果“搜索失败”?)

    【讨论】:

    • 如果我只想要一个完全匹配,为什么我希望他们返回 [String]...?而且,如何在代码中添加不匹配的条件?我的理解是,一旦 Haskell 找到第一个匹配项,它应该停止正在做的事情并返回......所以我认为我不需要担心多个匹配项?
    • 一次一个问题。 1.如果你想要一个完全匹配,你必须自己处理其他情况。使用case 语句,如case matches of [] -&gt; "a string you want to return when there are no matches"; (match:_) -&gt; match。 2. 没有匹配项时,无需添加任何额外代码即可返回空列表;它已经这样做了。 3. 你的理解不正确。您可能想查看您最喜欢的教程中的列表推导部分。
    • 我不知道如何使用case 语句。我会寻找一些例子。并查看列表理解。
    • 参见上面的新搜索功能。这表示“不匹配”部分的“模式解析错误”
    • @Special--k 好的,我已经更新了答案。然而,在未来,你应该为你试图解决的每一个不同的问题开始一个新的问题;否则,问题和答案可能会变得混乱,不同步。
    【解决方案2】:

    嗯,让我们看看。你有一个东西清单,[a]。您有一些标准来确定搜索是否成功,a -&gt; Bool。并且您想在列表中执行搜索,返回元素类型a 的值。停止......胡歌时间! Hoogling [a] -&gt; (a -&gt; Bool) -&gt; a,最热门的是find :: (a -&gt; Bool) -&gt; [a] -&gt; Maybe a。唯一的问题是它返回一个Maybe a:它将找到Just somethingNothing。我会说这是对您的 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 -&gt; String 作为字段访问器来从Entry 中提取def。但是我们如何将其应用于Maybe Entry

    停止...胡闹时间!我们有一个值,v :: Maybe a。我们有一个函数可以处理普通的旧af :: a -&gt; b。我们想以某种方式将f 应用于v,产生b 类型的结果。 Hoogling Maybe a -&gt; (a -&gt; b) -&gt; 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。 Maybe 是一个仿函数,这意味着我们可以在可能的值上使用fmap

    search' :: (Entry -> Bool) -> [Entry] -> Maybe String
    search' f es = fmap def $ find f es
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-12
      • 1970-01-01
      • 2014-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多