簡體   English   中英

如何寫一個類型為`[(a,b)] - >([a] - > [a]) - > [(a,b)]的函數

[英]How to write a function of type `[(a,b)] -> ([a] -> [a]) -> [(a,b)]`

我有一個關聯列表

L :: [(a,b)]

其中每個a都與b相關聯。

b只是額外的信息,有趣的部分是a

我想使用a ,所以我有[a] -> [a]類型的函數f (在我的問題中,我實際上有[a] -> [[a]] ,所以如果你的答案會推廣到我可以遍歷的任何容器,這將是好的。

我想我需要類似的東西

[(a,b)] -> ([a] -> T a) -> T (a,b)

其中T是我可以遍歷的某種容器)。 這個函數基本上重新排列了a ,它不會創建新的,也不會刪除任何東西。

我似乎已經陷入了在[(a,b)] a一部分上運行f的最慣用的方式,並在最后附上b

我想用的Data.Map簡單地做在最后的查找,但我不知道是否有更好的方法做什么,我以后,不知何故“線沿”的b與計算的其余部分一起。

如果沒有,你能解釋一下原因嗎?

顯而易見的另一種方法是重寫f但我不希望這樣,因為f不關心b

非常感謝您的幫助。

你的類型b “只是額外的信息”讓我想起了Env comonad,這是最簡單的comonad之一,可用於將有用的額外信息附加到值。

import Control.Comonad
import Control.Comonad.Env

toenv :: [(a,b)] -> [Env b a]
toenv = map (\(a,b)->env b a)

也許你可以重寫你的類型[a] -> [a]的函數來處理更常見的類型Comonad w => [wa] -> [wa] ,comonad中的多態。 如果你必須生成新的值,這將是一個問題(comonads不提供將值放在comonadic上下文中的一般方法),但由於你只想重新排序現有的值(或刪除它們),它將正常工作。

請記住,你可以隨時可以得到a從值wa使用extract功能。

要從通用函數中恢復原始[a] -> [a]函數,只需使用Identity comonad。

import Control.Comonad.Identity

simplify :: Functor f => (forall w. Comonad w => f (w a) -> f (w a)) -> f a -> f a
simplify f = fmap extract . f . fmap Identity

假設你有一個

rearrange :: [a] -> [a]

但你想重新排列像[(a,b)]這樣的列表。

你只需重寫重新排列

rearrangeBy :: (c -> a) -> [c] -> [c]

在檢查位置上用(fx)代替元素x的出現

然后重寫傳遞新目標函數的目標函數

targetfun :: ((c -> a) -> [c] -> [c]) -> [(a,b)] -> [(a,b)]
targetfun rearrangeBy pairList = rearrangeBy fst pairList

該功能可以像這樣實現:

  1. 從該關聯列表中提取密鑰列表
  2. 將“重新排列”功能應用於此密鑰列表以獲取新密鑰列表(可能嵌入容器中)
  3. 將該新密鑰列表中的每個密鑰映射到原始關聯列表中的對應對

以上描述可以直接轉換為Haskell代碼:

generalArrange :: (Functor f, Eq a, Show a) => [(a, b)] -> ([a] -> f a) -> f (a, b)
generalArrange al f = fmap keyToPair $ f as
    where as = map fst al
          keyToPair k = lookup k al
          lookup k [] = error $ "Invalid key: " ++ show k
          lookup k (a:as)
            | k == fst a = a
            | otherwise = lookup k as

測試:

ghc > let al = [(2, "def"), (1, "abc"), (3, "ijk")]
ghc > generalArrange al sort
[(1,"abc"),(2,"def"),(3,"ijk")]

[a] -> T a函數中無法“繞過”另一種類型的值。 一旦應用了,你將需要一些方法來查找每個a的相應b 我認為你對Map的想法是關於你可以做的最好而不重寫f 依賴於aHashMapIntMap可能在您的特定情況下更好地工作。

暫無
暫無

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

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