在Prelude的null
函數的定義如下:爲什麼Haskell Prelude中的null函數的定義很奇怪?
null :: [a] -> Bool
null [] = True
null (_:_) = False
什麼讓我感到困惑的是定義的第三行,爲什麼不把它寫:
null(_:_) = False
相反的:
null any = False
它與編譯器優化有什麼關係?
在Prelude的null
函數的定義如下:爲什麼Haskell Prelude中的null函數的定義很奇怪?
null :: [a] -> Bool
null [] = True
null (_:_) = False
什麼讓我感到困惑的是定義的第三行,爲什麼不把它寫:
null(_:_) = False
相反的:
null any = False
它與編譯器優化有什麼關係?
它與編譯器優化有什麼關係?
非也,其實可以說,寫null (_:_)
比null any
效率更低(如果編譯器不優化了這一點),因爲現在你問哈斯克爾驗證它確實是一個「缺點」。雖然如果編譯器在數據類型上做了一些簿記,那麼優化它當然很容易。據我所知,大多數編譯器如ghc
和差不多所有不是由三歲孩子編寫的編譯器確實會這樣做。所有的
首先,它是更好的不寫wilcard _
(或命名any
),因爲列表的定義(以及任何其他數據類型可能會改變)。雖然列表的可能性不大,但有人可能會重新定義一個列表。例如,如:
data [a] = [] | (a:[a]) | (Int///[a])
其中例如後一種模式意味着該列表重複多次。在那種情況下,一個不是由三歲小孩編寫的編譯器:)將警告大約對於null
不完整的模式:它將因此聲稱(_///_)
模式未被指定。而如果您使用通配符,它將回退到null any
的情況。
一般來說,最好小心使用通配符:只有當你真的不關心給函數賦予什麼時,你應該使用通配符。
沒有。沒關係。這個定義非常清楚地表明,沒有錯過任何東西,但對於那些實際上並不重要的列表。 – dfeuer
另外,你可以定義'null = all(const False)'。也許這會更清楚。 – dfeuer