2015-10-21 13 views
14

(*~) işlevim var. x *~ y değerlendiren maliyetinin çoğu kabaca bu satırlar boyunca, ikinci argüman teftiş geliyor: Kısmen (*~ y) gibi operatör bölümlerini değerlendirmek için ghc ikna etmenin bir yoluKısmen sağ elle çalışan kullanıcı bölümlerini değerlendirmek

(*~) :: a -> b d -> c d a 
x *~ y = case y' of 
      Bar -> cheapFunction y' x 
      Baz -> cheapFunction2 y' x 
      Quux -> cheapFunction3 y' x 
    where 
    y' = expensive y 

var mı?

ben gibi yeniden denedi:

(*~) = flip go 
    where 
    go y = let y' = expensive y 
      in case y' of 
       Bar -> cheapFunction y' 
       Baz -> cheapFunction2 y' 
       Quux -> cheapFunction3 y' 

ama yardımcı görünmüyordu. Bunun nedeni, flip'un saygısızlık yapmadan önce tüm argümanlarını gerektirmesi olabilir.

Tek yol, yalnızca operatörün kendisini çevirmek olabilir, ancak pahalı işlenen sağ tarafta olduğunda, daha çok doğal olarak okur, çünkü varolan bir gösterimle hizalanır.

Düzgün hazırlanmış bir {-# RULE #-} beni buradan kurtarır mı? Eğer öyleyse, ne söylemeli? (Ben kurallar sözdizimi, diğer şeylerin yanı sıra, eşleşmeleri aramaya başlamadan önce ne kadar uzağa düşmüş olacağımı açıklığa kavuşamıyorum.)

+1

Kısmi değerlendirmenin sizi satın alacağından emin değilim. zaten paylaşılacaksınız. Memoization istiyor musunuz? Notu kendiniz eklemeniz gerekecek. Ne tür bir kural yazmak istersin? –

+1

Özel bir 'çevirme 'kullanırsanız ne olur? 'flip' f x = \ y -> satır içi f y x' – dfeuer

+2

@ReinHenrichs '' 'zaten paylaşılacak mı? Eğer öyleyse benim anlayışım oldukça bozuk ve nasıl olduğunu açıklayan bir cevabı kabul etmeyi çok isterim. Eğer fmap (* ~ y) bazıLongList 'i yaparsam her seferinde yeniden hesaplanmayacak mı? –

cevap

5

Böyle bir optimizasyonu tetiklemek için, işlevinizin satır içi olduğundan emin olmanız gerekir. (*~) işlevinin bildirilmesinden önce {-# INLINE (*~) #-} pragma yerleştirin. Sorunu çözeceğini garanti edemem, ama yaklaştığımı görmenin tek yolu bu. Bundan emin olmak için üretilen Core kodunu "ghc-core" gibi bir araçla inceledim. Bununla birlikte, sorun aslında doğru olmayan kod kompozisyonunun bir göstergesidir. Fonksiyonunuz birbiriyle ilgisiz şeyler yapıyor. expensive y sadece bunun dışına çıkarılmalıdır, o zaman probleminiz bu şekilde silinecektir. Örneğin, kullanım modeli x *~ y yerine x *~ expensive y olmalıdır.

+1

Bu iyi bir nokta ve sorunu çözecektir. Ama 'pahalı' sonuç türü şu anda gizli bir uygulama detayıdır, çünkü kütüphanenin kullanıcılarının ilgisini çekmez (' ~) '. –

+2

Aslında, sizin durumunuzda gizli bir uygulama detayı olmayacak, sadece farklı bir şekilde açığa çıkacaksınız. Ayrıca niyet obfuscating ve tip sistemden bu gizleme ve dolayısıyla aksi takdirde özel işlev kullanılacak gerekiyordu nasıl kullanıcıyı bilgilendirmek zorunda kalacak olurdu. Bu, kullanılabilirlik açısından iyi olmayabilir. Ve yine, endişelerin ayrılmasına karşı giderdi. Yaklaşımınızın zaten yanlış olduğunu gösteren bir işaretler listesi var, bu yüzden iki kez daha iyi düşünün. –

+0

İyi noktalar var. –