簡體   English   中英

使用地圖和$用於函數應用程序的Haskell eta約簡

[英]Haskell eta reduction using map and $ for function application

嗨,我有一個任務來編寫一個函數,該函數從Int -> Int和單個Int中獲取函數列表,並檢查應用於該Int函數是否得出大於5的結果。

這是我的解決方案:

foo :: [Int -> Int] -> Int -> Bool
foo ls = any (>5) . f ls
     where f ls v = map ($ v) ls

我想知道是否有一種方法可以用eta減少最后一個參數(現在是eta減少但不是單行)在單行中編寫(不使用where或let)。 我嘗試過這樣的事情:

foo ls = any (>5) . flip map ls

但是現在的問題是調用函數看起來像這樣才能正常工作

foo [(+3), (*4), (+1)] ($2)

我想避免在最后一個論點中寫$。 我嘗試過這樣的事情(和類似的事情):

foo ls = any (>5) . flip map ls ($)

但是我總是會遇到一些錯誤。 請注意,我不能更改類型簽名,也不能更改翻轉。

有辦法嗎? 當然。 可讀嗎? 不能。Haskell的設計使您擺脫一些常見的錯誤,例如不必要的可變性或(必要的)可變狀態的隱藏使用。 但是,遵循其他錯誤的方法也很令人興奮,例如以有害於可讀性和可維護性的方式使代碼毫無意義。

關於無點定義的問題是,轉換為無點定義是一個完全機械的過程(只要開始定義中不涉及模式匹配)。 有一些工具可以自動執行。

首先編寫完全eta擴展的定義:

foo ls x = any (>5) (map ($ x) ls)

然后將其放入您喜歡的工具中進行轉換。 http://pointfree.io/是將執行此操作的在線服務。

它吐出了完全不可讀的內容:

foo = (any (> 5) .) . flip (map . flip id)

不要使用它。 這不值得。

但是也許您只想縮小一個論點的范圍,這太多了嗎? 好吧,您可以通過作弊一點,並假裝第一個參數是作用域中的值而不是參數,然后在其中添加以下定義來做到這一點:

foo x = any (>5) (map ($ x) ls)

返回foo = any (> 5) . flip map ls . flip id foo = any (> 5) . flip map ls . flip id foo = any (> 5) . flip map ls . flip id ,然后將其插入回:

foo ls = any (> 5) . flip map ls . flip id

這要好一些,這要歸功於缺少(.)運算符的各個部分。 但是它仍然具有flip id ,這是最簡單的混淆。

不要這樣 保持克制。 編寫易於閱讀和修改的代碼。

從完全非簡化的定義開始:

foo ls v = any (>5) (map (\f -> f v) ls)

我們可以使用lambdabot擁有完全減少eta的解決方案:

foo = (any (> 5) .) . flip (map . flip id)

但是,這看起來很糟糕,不建議這樣做。

其實,您在問題中的最后一次審判

foo ls = any (>5) . flip map ls ($)

已經非常接近解決方案。

唯一的問題是,考慮($)的定義:

($)::(a -> b) -> a -> b

的第一個參數($)是一個函數(a->b)但在你的情況下,也可以是值a ,所以才flip ($)交換的參數的順序($)並把它早在:

foo ls = any (>5) . flip map ls . flip ($)

是您想要的功能。

由於您手頭有一個應用列表,因此您可以簡單地用應用運算符<*>將其應用為[(+3), (*4), (+1)] <*> [2]以獲取結果列表,例如作為[5,8,3] 現在可以使用它了any :: Foldable t => (a -> Bool) -> ta -> Bool函數。 所以在一起

checker x = any (>5) $ [(+3), (*4), (+1)] <*> [x]

應該做的工作。 如果您需要沒有積分的版本,它將比

checker = any (>5) . ([(+3), (*4), (+1)] <*>) . pure

暫無
暫無

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

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