[英]Reduction of list through partial application in Haskell
對於具有多個參數的函數,是否有一些功能更強大的map? 因此,精簡列表的長度將是length of original / number of arguments
...
tuple a b = (a, b)
map' tuple [1, 2, 3, 4]
> [(1, 2), (3, 4)]
mul a b c = a * b * c
map' mul [1, 2, 3, 4, 5, 6]
> [3, 120]
我試圖為自己寫一個,但是似乎無法接受任何數量的參數的功能。
我想為可變數量的參數提供通用版本,因為每次自己編寫一個會花費一些時間,並且不會使用循環融合。
最簡單的解決方案是只為您需要的每個Arity生成一個輔助函數,例如,針對Arity 3函數:
map3 :: (a -> a -> a -> b) -> [a] -> [b]
map3 f (x : y : z : rest) = f x y z : map3 f rest
map3 f _ = []
將它們放在實用程序模塊中,以便您可以根據需要導入它們。 如果您想變得復雜,可以使用TemplateHaskell,CPP宏甚至類型類來生成它們,但是要小心,不要將這個簡單的練習變成a牛刮胡子聚會。
你的例子:
interact $ unlines . fmap foo . tuple . lines
然后可以表示為:
interact $ unlines . map2 foo . lines
假設foo
具有簽名foo :: String -> String -> String
我不同意定義這樣的東西的精神,但是僅僅出於它的狹och性,我正在努力嘗試它。 這是一個有效的解決方案,但僅適用於單態類型。 我正在研究是否可以將其轉換為涉及類型族的東西,這些類型族也不需要亂用類型注釋。
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}
class Consumer f a b where
consume :: f -> [a] -> Maybe (b,[a])
instance {-# OVERLAPPABLE #-} Consumer b a b where
consume b xs = Just (b,xs)
instance {-# OVERLAPPING #-} Consumer f a b => Consumer (a -> f) a b where
consume f [] = Nothing
consume f (x:xs) = consume (f x) xs
map' :: Consumer f a b => f -> [a] -> [b]
map' f xs = case consume f xs of
Nothing -> []
Just (b,xs') -> b : map' f xs'
並進行測試
> map' ((+) :: Int -> Int -> Int) ([1,2,3,4] :: [Int]) :: [Int]
[3,7]
> map' (id :: Int -> Int) ([1,2,3,4] :: [Int]) :: [Int]
[1,2,3,4]
經過一番思考,我認為不可能有更好的解決方案(沒有依賴類型)。 我之所以要到處添加類型標注的是,我沒有辦法告知GHC的,我已經提供的兩個實例消費者其實我都不會想的唯一實例(是密閉式班甚至一個東西嗎?)我可以”提取功能依賴性。 第二個問題也是為什么我不能將其重寫為類型族。 在一個側面說明,雖然,注釋功能參數可以看起來要好很多,現在我們有TypeApplications
: map' ((+) @Int) ([1..9] :: [Int])
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.