2015-01-12 113 views
1

我有以下函數,它用一個Int輸入分割一個Maybes列表。遞歸列表理解[Haskell]

divideList :: Int -> [Maybe Int] -> [Maybe Double] 

divideList 100 [Just 5, Just 4, Nothing] == [Just 20, Just 25.0, Nothing] 

需要提醒的可能數據類型定義如下:

data Maybe a = Nothing | Just a 

我的代碼如下(和作品)爲如下:

divideList m xs = [ div2 x | x <- xs] 
    where 
     div2 (Just n) | n > 0 = Just (fromIntegral m/fromIntegral n) 
     div2 _     = Nothing 

現在我正在嘗試編寫相同的功能再次,但這次只是遞歸和沒有列表解析。然而,我似乎無法得到它的工作。

這裏是我的(錯誤)猜測:

divideList m xs = div2 x 
    where 
     div2 (Just x) | x > 0 = Just (fromIntegral m/fromIntegral x) 
     div2 _     = Nothing 

回答

4

你幾乎沒有。

  1. 首先定義的劃分函數分別

    div3 :: Int -> Maybe Int -> Maybe Double 
    div3 i (Just n) | n > 0 = Just (fromIntegral i/fromIntegral n) 
    div3 i _    = Nothing 
    
  2. 然後,對於列表中的每個項目,調用div3並與遞歸調用divideList的結果並置,就像這樣

    divideList :: Int -> [Maybe Int] -> [Maybe Double] 
    divideList _ [] = [] 
    divideList m (x:xs) = (div3 m x):(divideList m xs) 
    

這裏,

divideList _ [] = [] 

被稱爲您的遞歸的基準條件。這決定了遞歸何時結束。

+1

我想提一提,這基本上是專門用於'div3'的'map'功能。 – bheklilr

+1

@bheklilr因爲他已經知道列表理解,我猜可以放心地假設他也知道'map'。 :) – thefourtheye

+0

它的工作!榮譽! – user3086819

3

我總是推薦的是:做不是寫直接遞歸解決方案,就像你想要做的。他們不是慣用的,他們很難閱讀,而且一旦你做了任何複雜的事情,他們都很難寫。

相反,要弄清楚如何使用標準庫函數(如map,filter等)編寫解決方案。然後,作爲練習,編寫您自己的這些庫函數的版本。在這種情況下:

divideList m xs = map div2 xs 
    where 
     div2 (Just n) | n > 0 = Just (fromIntegral m/fromIntegral n) 
     div2 _     = Nothing 

-- Apply the function `f` to each element of the list, returning a list of the results, 
-- in the order of the corresponding arguments. 
map f []  = _ -- Fill me in 
map f (x:xs) = _ -- Fill me in 
1

我建議先寫一個函數來除以兩個整數。它必須返回一個Maybe Double,因爲計算不總是可能的。

div2 m n = if n <= 0 then Nothing else Just (fromIntegral m/fromIntegral n) 

然後你只需要這一功能應用到列表中的每一個元素,它可以與map完成。但是,由於該號碼「隱藏」在Maybe中,因此可以使用功能(>>=)「解包」它(當它不是Nothing時,它會保留Nothing,如我們所需)。

divideList m xs = map (>>= div2 m) xs 

或更短:

divideList m = map (>>= div2 m)