簡體   English   中英

Haskell中沒有“長度”函數的列表的長度

[英]The length of a list without the "length" function in Haskell

我想查看列表的長度,但不使用函數length 我寫了這個程序,但它不起作用。 也許你能告訴我為什么? 謝謝!

let y = 0
main = do
  list (x:xs) = list (xs)
  y++

list :: [Integer] -> Integer
list [] = y

您的程序看起來非常“ 必要 ”:您定義了變量y ,然后以某種方式編寫了一個do ,它調用(?) list函數(?),該函數似乎自動“返回y ”,然后您想要遞增y

那不是Haskell(以及大多數功能性和聲明性)語言的工作方式:

  • 在聲明性語言中,僅定義一次變量 ,設置值后,通常無法更改其值,
  • 在Haskell中, do通常用於monad,而length是一個函數,
  • let是用於在表達式范圍內定義變量的語法構造,
  • ...

為了對Haskell(或任何功能性語言)進行編程,您需要“考慮功能性”:思考如何使用函數數學方式解決問題。

在數學中,您會說空列表[]長度顯然為0 此外,如果列表不為空,則存在第一個元素(“頭”)和其余元素(“尾”)。 在這種情況下,結果為一加尾的長度。 我們可以將其轉換為數學表達式,例如:

膠乳

現在,我們可以輕松地將該函數轉換為以下Haskell代碼:

ownLength :: [a] -> Int
ownLength [] = 0
ownLength (_:xs) = 1 + ownLength xs

現在在Haskell中,通常還使用累加器來執行尾部遞歸 :您通過遞歸調用傳遞參數,並且每次更新變量時都會傳遞該參數。 遞歸結束時,有時會經過一些后處理后返回累加器。

在這種情況下,累加器將是迄今為止看到的長度,因此您可以編寫:

ownLength :: [a] -> Int
ownLength = ownLength' 0
    where ownLength' a [] = a
          ownLength' a (_:xs) = ownLength' (a+1) xs

看起來您仍然以命令式的方式(而不是功能性的方式)思考。 例如:

  • 您嘗試更改“變量”(即y++ )的值
  • 您嘗試在list函數的主體中使用“全局變量”(即y

這是您的問題的可能解決方案:

main = print $ my_length [1..10]

my_length :: [Integer] -> Integer
my_length [] = 0
my_length (_:xs) = 1 + my_length xs

您也可以在以下位置運行此代碼: http : //ideone.com/mjUwL9

另請注意,無需要求您的列表包含Integer數值。 實際上,可以通過使用以下聲明來創建函數的更多“不可知論”版本:

my_length :: [a] -> Integer

此功能的實現不依賴於列表中項目的類型,因此您可以將其用於任何類型的列表。 相反,例如my_sum函數(一個可能的函數可以計算給定列表中元素的總和)就不能那么自由。 在這種情況下,您應該定義列表由一些數字類型項組成。

最后,我想向您推薦一本關於Haskell編程的出色書籍: http : //learnyouahaskell.com/chapters

其他答案已經很好地解釋了正確的功能方法。 看起來有些矯kill過正,但這是通過僅使用可用的高階函數來實現length函數的另一種方法。

my_length :: [a] -> Integer
my_length = foldr (flip $ const . (+1)) 0

我在Learn you a haskell 中找到了這個解決方案。

length' xs = sum [1 | _ <- xs]

它將列表中的每個元素替換為 1 並將其求和。

可能最簡單的方法是將所有元素轉換為1 ,然后對新元素求和:

sum . map (const 1)

為了提高速度:

foldl' (+) 0 . map (const 1)

暫無
暫無

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

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