簡體   English   中英

Haskell:使用(curry snd)計算列表的長度

[英]Haskell: Calculate the length of a list using (curry snd)

我得到了一個使用foldr Haskell 函數計算列表長度的作業,所以我做了這兩個例子

flength :: [a] -> Int
flength = foldr (\ _ n -> n+1) 0

flength' :: [a] -> Int
flength' l = foldr aux 0 l
    where
        aux _ n = n+1

然后,作為個人挑戰,教授要求我們使用snd函數,昨天我想出了這個:

flength'' :: [a] -> Int
flength'' = foldr ((+1).(curry snd)) 0

我想要發生的是這個函數將把列表的頭部h和累加器0變成對(h,0)然后返回0然后將它應用到函數(+1)

我希望這是遞歸完成的,最后有效地給了我列表的長度。

相反,我收到此錯誤消息:

    [1 of 1] Compiling Main             ( f1.hs, interpreted )

f1.hs:54:24: error:
    * No instance for (Num (Int -> Int))
        arising from an operator section
        (maybe you haven't applied a function to enough arguments?)
    * In the first argument of `(.)', namely `(+ 1)'
      In the first argument of `foldr', namely `((+ 1) . (curry snd))'
      In the expression: foldr ((+ 1) . (curry snd)) 0 xs
Failed, modules loaded: none.

為什么會發生這種情況以及如何使此代碼正常工作?

讓我們把所有的工具都擺在我們面前,就像一個好的工匠一樣:

foldr :: (a -> b -> b) -> b -> [a] -> b
snd   :: (a, b) -> b

首先,我們注意到sndfoldr不太適合。 因此,讓我們像您一樣使用curry ,並將curry snd添加到我們的小型工具庫中:

foldr     :: (a -> b -> b) -> b -> [a] -> b
curry snd ::  a -> b -> b

這看起來很有希望。 現在我們需要將curry snd的結果加1 ,否則我們只是在寫flip const 讓我們從一個 lambda 開始:

\a b -> 1 + curry snd a b
= \a b -> ((+1) . curry snd a) b

我們現在可以推b並最終得到

\a -> (+1) . curry snd a
= \a -> (.) (+1) (curry snd a)
= \a -> ((.) (+1)) (curry snd a)
= \a -> (((.) (+1)) . curry snd) a

現在我們也可以從兩邊對a進行 eta-reduce 並最終得到

(((.) (+1)) . curry snd) = ((+1) . ) . curry snd

因此,您的第三個變體將是

flength'' = foldr (((+1) . ) . curry snd) 0

現在,您為什么會收到錯誤消息? 你很接近(+1) . curry snd (+1) . curry snd ,但類型不工作:

(+1)      :: Int -> Int
--            v                    v
(.)       :: (b ->  c)    -> (a -> b       ) -> a -> c
curry snd ::                  t -> (x -> x)
              ^                     ^

但是在您的情況下, (.)簽名中的b不匹配。 其中一個是Int ,另一個是函數。

TL;DR : 如果你想寫f (gxy) point-free,寫((f.) . g)

暫無
暫無

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

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