2015-01-23 23 views
5

bu kat daha genel yapabilir:nasıl bu fonksiyonu yazdım

{-# LANGUAGE RankNTypes #-} 
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE TemplateHaskell  #-} 
{-# LANGUAGE TypeFamilies   #-} 
module Hierarchy where 

import   Control.Applicative 
import qualified Control.Foldl  as CF 
import   Control.Foldl (Fold(..)) 
import   Control.Lens hiding (Fold) 
import qualified Data.Foldable  as F 
import qualified Data.Map.Lazy  as M 
import   Data.Monoid   (Monoid (..), Sum (Sum)) 
import   Data.Profunctor 
import   Data.Set (Set) 
import   Data.Maybe 
import   Data.Text   (Text) 

overMaps :: (Ord k) => Fold a b -> Fold (M.Map k a) (M.Map k b) 
overMaps (Fold step begin done) = Fold step' M.empty (fmap done) 
    where 
    step' acc m = M.foldrWithKey insert acc m 
    insert k el acc = M.insert k (step (fromMaybe begin $ M.lookup k acc) el) acc 

Ben bu daha genel yapabilir bazı temel soyutlama kaçırıyorum gibi hissediyorum ve daha özlü.

kimse Bunu düzeltmek için buraya herhangi bir modern Haskellisms kullanabilirsiniz nasıl olarak bana biraz öğüt verebilir misiniz?

düzenlemek kod burada https://github.com/boothead/hierarchy/blob/master/src/Hierarchy.hs

ve ben ithalatı

düzenlemek Belki @ cdk- fikri yaklaşmak için ifoldr kullanabilir yer verdik?

düzenlemek İşte

bende en yakın bulunuyor.

--overFoldable :: (Ord k) => Fold a b -> Fold (M.Map k a) (M.Map k b) 
overFoldable :: (Ord i, At (f i a), FoldableWithIndex i (f i), Monoid (f i x)) 
      => Fold a b -> Fold (f i a) (f i b) 
overFoldable (Fold step begin done) = Fold step' mempty (fmap done) 
    where 
    step' acc m = Lens.ifoldr insert acc m 
    insert k el acc = Lens.at k %~ return . flip step el . fromMaybe begin $ acc 

İlk (yorum yazdığınız) imza işlerini burada işler. Şimdi problem benim yeni kıvrımın begin pozisyonunda koymak için anlamaya olamaz Fold :: (x -> a -> x) -> x -> (x -> b) -> Fold a b tipi imzası varoluşsal x yatıyor. Bu Tip f i x olması gerekiyor ama begin aynı tip olması x almaya nasıl Haskell nasıl söyleyeceğimi bilemiyorum.

+1

kesildi geldiği gibi. –

+2

@SebastianRedl http://hackage.haskell.org/package/foldl adresinde, – ocharles

+1

'a inanıyorum. Bir bakışta 'overMaps :: Katlanabilir f => Fold a b -> Fold (f a) (f b)' neredeyse ümit verici görünüyor. Ne yazık ki ben 'katlanabilir 'sınıfı' Katlanabilir 'sınıf – cdk

cevap

4
Çoğunlukla kendi anlayış için

(ve o benim sevgili rubber duck):

varsayalım Ben ben overMaps sumLengths bir olmak istiyorum

dizeleri (şimdiye fold sumLengths ["a","bbb"] verimleri 4) uzunluklarının ekleyen bir Katlama sumLengths Kıvrım aldığı Fransız ve Hollandalı sözlüğü söylemek alır ve lookup D "bread" elbette sorun öyle mi 9 (length("pain") + length("brood"))

olduğunu D böyle yeni sözlük yapar Bana kelimeler bütün sözlüklerde gerçekleşmeyebilir: lookup D "sex" Hollandalı yüzden bizim kat başında sadece bizim kıvrım begin değerine ihtiyacımız :-) çok iffet taslayan olarak length("sexe") olmakla muhtemelen her an.

Bu, baştan beri bizim begin değerini almak zorunda sadece (aşağıya bakınız, bunun yerine bizim Map ait Applicative herhangi bir örneğini kullanabilirsiniz bu durumda) Map k için step fonksiyonunu kaldırmaya yapmayacağım anlamına gelir yol.

Bu "lift artı varsayılan değer" FusableFusable yeni bir sınıf üyesidir. Bu orijinal kodunda step', ama biz de örneğin listelerin listeleri için bir overF sumLengths olması için (biraz) genelleştirilmiş. biz birlikte begin değerini alarak endişe yoksa

import Data.Map as M hiding (map) 
import qualified Control.Foldl  as CF 
import Control.Foldl (Fold(..)) 
import Control.Applicative 
import Data.Foldable as F 
import Data.Maybe 

--- the Fusable class: 
class Functor f => Fusable f where 
    fuseWith :: x -> (x -> a -> x) -> f x -> f a -> f x 
    emptyf :: f a 

--- Map k is a Fusable (whenever k has an ordering) 
instance (Ord k) => Fusable (Map k) where 
    fuseWith x f xmap amap = M.foldrWithKey insert xmap amap where  
     insert k el xmap = M.insert k (f (fromMaybe x $ M.lookup k xmap) el) xmap 
    emptyf = M.empty 

--- Lists are Fusable 
instance Fusable [] where 
    fuseWith = zipWithDefault where 
    zipWithDefault dx f [] ys = zipWith f (repeat dx) ys 
    zipWithDefault dx f xs [] = xs 
    zipWithDefault dx f (x:xs) (y:ys) = (f x y) : zipWithDefault dx f xs ys 
    emptyf = [] 

--- The generalised overMaps: 
overF :: (Fusable f) => Fold a b -> Fold (f a) (f b) 
overF (Fold step begin done) = Fold (fuseWith begin step) emptyf (fmap done) 

--- some tests 
testlist = [(1,4),(3,99),(7,999)] 
testlist2 = [(1,15),(2,88)] 

test = CF.fold (overF CF.sum) $ map fromList [testlist, testlist2] 
-- fromList [(1,19),(2,88),(3,99),(7,999)] 
test2 = CF.fold (overF $ CF.premap snd CF.sum) [testlist, testlist2] 
-- [19,187,999] 

, herhangi Applicative (Map kApplicative değil kullanabilirsiniz!

overA :: (Applicative f) => Fold a b -> Fold (f a) (f b) 
overA (Fold step begin done) = Fold (liftA2 step) (pure begin) (fmap done) 

Kesinlikle overF gibi görünüyor. Ama farklı sonuçlar verir: en kısa sürede, listelerin bir liste üzerinde katlarken bir liste olduğunu çok kısa boyunca, sonuç bir typeclass `Hoogle içinde Fold` bulamıyorum

test3 = CF.fold (overA $ CF.premap snd CF.sum) $ map ZipList [testlist, testlist2] 
-- ZipList [19,187] -- *where* is my third element :-(