0

我在寫一個遞歸函數mxAndC。當我給它一個列表時,它應該返回一個元組。元組將具有給定列表的最大值作爲其第一個元素,第二個元素將是該元素在列表中出現的次數。作業不允許我創建輔助函數。我期待下面的輸出:返回列表的最大值和出現次數的函數

mxAdC "bananas" = (s,1) 

mxAdC "banana" =(n,2) 

mxAdC [mod x 4 | x <- [1..50]] -> (3,12) 

我做了以下內容:

mxAdC = go 0 
where go count (x:xs) 
      | count /= 0  = (mx, count) 
      | null ((x:xs)) = error "The list is empty" 
      | x == mx   = go (count+1) xs 
     where mx = maximum (x:xs) 

而且我得到錯誤:

* Ambiguous type variable `a0' arising from a use of `go' 
     prevents the constraint `(Ord a0)' from being solved. 
     Relevant bindings include 
     mxAdC :: [a0] -> (a0, Integer) (bound at hw06.hs:24:1) 
     Probable fix: use a type annotation to specify what `a0' should be. 
     These potential instances exist: 
     instance (Ord a, Ord b) => Ord (Either a b) 
      -- Defined in `Data.Either' 
     instance Ord Ordering -- Defined in `GHC.Classes' 
     instance Ord Integer 
      -- Defined in `integer-gmp-1.0.0.1:GHC.Integer.Type' 
     ...plus 23 others 
     ...plus 38 instances involving out-of-scope types 
     (use -fprint-potential-instances to see them all) 
    * In the expression: go 0 
     In an equation for `mxAdC': 
      mxAdC 
      = go 0 
      where 
       go count (x : xs) 
        | count /= 0 = (mx, count) 
        | null ((x : xs)) = error "The list is empty" 
        | x == mx = go (count + 1) xs 
        where 
         mx = maximum (x : xs) 

我在Haskell很新。那裏的任何善意的專家都喜歡伸出手幫助這個新手?

+1

你應該爲你的函數添加類型簽名。 – duplode

+0

[Haskell:這個代碼中的錯誤來源是什麼「Ambiguous type variable ... \' Integral t'...''RealFrac t'...」)(http://stackoverflow.com/questions/3642277/haskell-what-is-the-source-of-error-ambiguous-type-variable-integral-t) – duplode

+1

@duplode:我認爲這不是真的重複。另一個問題有一個_contradicting_類型,這個原則上是可行的,但有一個單態限制問題。相同的錯誤消息,但是完全不同的底層問題。 – leftaroundabout

回答

0

一個相當簡單的應用中會使用filter

mxAdC :: Ord a => [a] -> (a,Int) 
mxAdC xs = (mx,length $ filter (\x -> x == mx) xs) where mx = maximum xs 
+0

我在mxAdC上得到解析錯誤 –

+0

您的輸入是什麼? – mnoronha

+0

這是編譯時錯誤。 –

0

你遇到了可怕的單態限制。

可以使用mxAdC x = go 0 x

  • {-# LANGUAGE NoMonomorphismRestriction #-}在你的文件
  • 添加型簽名
  • 你的功能仍然是錯誤的開始修復由

    • 類型錯誤,但現在它是typechecks。

      Haskell禁止看起來像頂級常量的多態函數(在=符號之前沒有參數)。所以一般來說你不能eta減少(用foo = bar代替foo x = bar x)。完整的解釋是相當長的 - 看到這樣的回答:https://stackoverflow.com/a/32496865/805266

    +2

    對,但** a)**這絕對不是解決方案的優先順序** b)**答案可以使用更多解釋。 – leftaroundabout

    +0

    把{ - #LANGUAGE NoMonomorphismRestriction#}仍然給出錯誤。 –

    +1

    @AliToto不,它不是。那麼,至少它不會給出你有關於_的問題。 – leftaroundabout

    0

    其他人解釋錯誤類型。讓我們看看更有趣的錯誤。

    | null ((x:xs)) = error "The list is empty" 
    

    怎麼了? x : xs從不爲空。它不可能,因爲它的第一個元素是x!你的意思在這裏做的是

    mxAdC ys 
        | null ys = error "mxAdC: the list is empty" 
        | otherwise = go 0 ys 
        where ... 
    

    下一個問題是

    | count /= 0  = (mx, count) 
    

    這是說只要數不爲零,就大功告成了。所以你永遠不會超過1.你認識到你的遞歸需要一個基本的例子,所以你試圖把一個,但你錯過了標記。你所需要的基本情況是對付空單:

    go count [] = ? 
    go count (x:xs) 
        | x == mx   = go (count+1) xs 
    

    東西還是從go失蹤,但是。你想在x /= mx時發生什麼?您需要添加更多的情況(我已經離開問號爲您填寫):

    go count [] = ? 
    go count (x:xs) 
        | x == mx   = go (count+1) xs 
        | otherwise  = ? 
    

    的最後一個主要問題是,你的go函數中定義mx。這將計算每次列表go交給的任何部分的最大值。你想要做什麼是mxAdC

    mxAdc ys 
        | .... 
        where 
        go ... 
        mx = maximum ys 
    

    定義mx還有兩個大問題的效率來處理。一個問題是go不再強制在遞歸調用中計算累加器,這可能導致空間泄漏。一旦計算最大然後再次指望它出現的次數:這是很容易使用BangPatterns語言擴展與

    go !count [] = ? 
    go !count (x:xs) 
        | x == mx   = go (count+1) xs 
        | otherwise  = ? 
    

    最後一個問題是,你仍然遍歷列表兩次固定。只需一次就可以完成。我不會給你所有的細節,但基本的技巧是改變你的功能,以採取迄今爲止看到的最大的元素以及它被看到的次數。你必須調整mxAdC的其餘部分以適應,使用模式匹配來取代null