簡體   English   中英

該函數返回一個刪除了第一個和最后一個元素的新列表

[英]Function which returns a new list with the first and last elements removed

我對Haskell還是陌生的,正在嘗試一個簡單的練習。 我想編寫一個刪除列表的第一個和最后一個元素的函數。

我不需要檢查列表的長度。 我在一本書中發現,我有一種刪除第一個元素的方法,也有一種反轉列表的方法,但是我認為這可能比必須的復雜。 除了復雜性之外,我還知道第二行之后我做錯了什么,但我不知道為什么或如何解決。

這是我的代碼:

midList :: [a] -> [a]
midList [a] = tail [a]
[a] = reverse [a]
[a] = tail [a]
[a] = reverse [a]

首先要做的是確保您了解問題。 特別是,如果列表沒有元素或只有一個元素,您想發生什么? 在這種情況下,最簡單的事情可能只是返回空列表。 因此,讓我們這樣做。 我們可以將問題分為兩部分:

  1. 刪除列表的第一個元素
  2. 刪除列表的最后一個元素

Haskell的前奏定義了我們確實不想要的幾個函數,因此讓我們將它們隱藏起來:

import Prelude hiding (tail, init)

現在我們可以定義這些函數的更好版本。 tail將返回列表的第一個元素以外的所有內容, init將返回最后一個元素以外的所有內容。 然后我們可以寫

chop :: [a] -> [a]
chop xs = init (tail xs)

tail是最容易寫的。 我將提供骨骼,您可以填寫缺失的部分。

tail :: [a] -> [a]
tail [] = ????
tail (x : xs) = ????

init有點棘手。 請注意,其中一種情況將是遞歸的。

init :: [a] -> [a]
init [] = ????
init [x] = ????
init (x : xs) = ????

您需要在功能上編寫步驟。 您建議的代碼可以重寫為:

midList :: [a] -> [a]
midList xs = reverse (tail (reverse (tail xs)))

請注意,如果tail傳遞了空列表,它將使您的程序崩潰。 您可以並且應該避免這種情況,方法是:1)檢查列表中是否至少包含兩個元素,或者2)使用drop 1而不是tail ,這將只在空列表上返回[]

如果嘗試2),則可以保留函數類型。 對於方法1),可以使用Maybe [a]返回類型將錯誤報告給調用方。 更具體地說:

midList :: [a] -> Maybe [a]
midList xs@(_:_:_) = Just (reverse (tail (reverse (tail xs))))
midList _          = Nothing

模式_:_:_代表至少包含兩個元素的列表。

或者,同時使用inittail :前者刪除最后一個元素,后者則刪除第一個元素。

midList :: [a] -> Maybe [a]
midList xs@(_:_:_) = Just (init (tail xs))
midList _          = Nothing

但是,在這里要特別小心,因為通常最好避免使用inittail這樣的部分函數。 通常,如果使用更基本的方法(例如使用模式匹配)來工作,則永遠不要使用它們。

在這里,我會發現上面的代碼不是最理想的。 我希望使用以下代碼,對自己的“安全”版本的init進行編碼,以刪除最后一個元素(如果有),否則將報告錯誤。

midList :: [a] -> Maybe [a]
midList (_:xs@(_:_)) = safeInit xs
midList _            = Nothing

safeInit :: [a] -> Maybe [a]
safeInit [] = Nothing
safeInit (x:xs) = case safeInit xs of
   Nothing -> Just []
   Just ys -> Just (x:ys)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM