2012-02-11 20 views
13

daha yüksek mertebeden fonksiyonu Kaldırma: t bir monad trafo olduğunuBen türünde bir fonksiyonu inşa çalışıyorum Haskell

liftSumthing :: ((a -> m b) -> m b) -> (a -> t m b) -> t m b 

. Özellikle, bunu yaparken ilgileniyorum: Ben ama boşuna bazı Haskell sihirbazlık kütüphanelerini ile oynuyordu ve

liftSumthingIO :: MonadIO m => ((a -> IO b) -> IO b) -> (a -> m b) -> m b 

. Nasıl 'u doğru şekilde edinebilirim ya da bulamadığım bir yerde hazır bir çözüm var mı?

+1

Gah! Bütün Haskell neden bu kadar zor? Burada hiçbir kolay nokta yok :-( – drozzy

+3

@drozzy: Bu etiket aslında [cevap başına en yüksek ortalama upvotes'tan birine sahiptir] (http://data.stackexchange.com/stackoverflow/query/61353/tags-with-highest-average -answer-skorlar-en-1000-sorular-etiketler arasında, bu yüzden onlar her zaman kolay olmasa da, insanlar çabaları için ödüllendirilirler. – hammar

cevap

18

Bu, IO türünde negatif bir konum nedeniyle tüm MonadIO örneklerinde genel olarak yapılamaz. Belirli durumlar için bunu yapan bazı kütüphaneler vardır (monad-control,), ancak özellikle istisnalar ve benzer garip IO y şeyleri nasıl ele aldıklarına dair, anlamsal olarak sağlam olup olmadıklarına dair bazı tartışmalar olmuştur.

Düzenleme: Bazı kullanıcılar pozitif/negatif konum ayrımıyla ilgilenir. Aslında söyleyecek fazla bir şey yok (muhtemelen çoktan duymuşsunuzdur ama farklı bir adla). Terminoloji alt tür dünyasından gelir.

alttiplendirmesinde arkasında sezgi

" a bir a bir b yerine bekleniyordu yerde kullanılabilen b bir alt tipi (I a <= b yazacağım ki) 'dir" olmasıdır. Alt türlemeye karar vermek birçok durumda basittir; Ürünler için, a1 <= b1 ve a2 <= b2 gibi, her zaman çok basit bir kural olan (a1, a2) <= (b1, b2). Fakat birkaç zor durum var; örneğin, ne zaman a1 -> a2 <= b1 -> b2 karar vermeliyiz?

f :: a1 -> a2 numaralı bir işleve ve b1 -> b2 türünde bir işlev beklediğimiz bir bağlama sahibiz. Bu nedenle, b2 gibi, f dönüş değeri kullanacak, dolayısıyla a2 <= b2. Zor olan şey, f'un a1 olduğu gibi kullanması bile bağlamın f'u b1 ile sağlamasıdır. Bu nedenle, b1 <= a1 - bunu tahmin edebildiğinizden geriye doğru bakmalıyız! a2 ve b2'un "kovaryant" olduğunu veya "pozitif bir pozisyonda" olduğunu ve a1 ve b1 "kontravaryant" olduğunu veya bir "negatif pozisyonda" meydana geldiğini söylüyoruz.

(Hızlı kenara:? "Olumlu" ve "olumsuz" Bu çarpma motive neden bu iki tür düşünün:.? I

f1 :: ((a1 -> b1) -> c1) -> (d1 -> e1) 
f2 :: ((a2 -> b2) -> c2) -> (d2 -> e2) 

zaman f1 ler türü 'ın tipi f2 bir alt türü olması' gerektiğini Bu gerçekleri devlet (egzersiz: yukarıdaki kuralı kullanılarak bu kontrol edin):

  • Biz e1 <= e2 olmalıdır
  • Biz d2 <= d1 olmalıdır
  • ..
  • c2 <= c1 olmalıdır.
  • b1 <= b2 olmalıdır.
  • a2 <= a1 olmalıdır.

e1f1 tipinde pozitif bir pozisyonda da olduğu d1 -> e1 pozitif pozisyonda olduğu; dahası, e1, f1 türünde pozitif bir konumdadır (yukarıdaki gerçeğe göre kovaryant olduğundan). Tüm dönem içindeki konumu, her bir alt pozisyondaki pozisyonunun ürünüdür: pozitif * pozitif = pozitif. Benzer şekilde, d1 tüm tipte pozitif bir konumda olan d1 -> e1'da negatif bir konumdadır. Negatif * pozitif = negatif ve d değişkenleri gerçekten dezavantajlıdır. b1, a1 -> b1 türünde, (a1 -> b1) -> c1 negatif bir konumda olan pozitif bir konumdadır; bu, tümüyle negatif bir konumdadır. Pozitif * Negatif * Negatif = Pozitif ve Kovaryantı. Sen fikir edinmek)

Şimdi, MonadIO sınıfa bir göz atalım:.

class Monad m => MonadIO m where 
    liftIO :: IO a -> m a 

Biz alttiplendirmesinde açık bir beyanı olarak görebilirsiniz: Biz IO a bir alt tip olmak için bir yol veriyoruz Bazı beton m için m a. Hemen biliyoruz ki IO yapıcıları ile pozitif pozisyonlarda herhangi bir değer alabilir ve m s. Ama hepsi bu: IO negatif kurucuları m s'ye dönüştürmenin hiçbir yolu yok - bunun için daha ilginç bir sınıfa ihtiyacımız var.

+7

"nedeniyle" IO "tipi olumsuz bir pozisyonda "- bunun ne anlama geldiğini ve neden önemli olduğunu anlatabilir misin? –

+2

@DanBurton Bu konuda biraz yazdım. –

+0

Bu kesinlikle yardımcı olur. Monad-kontrolü yeterli miktarda tinkering yapmama izin verebilir. "ma" dan "tma" dan bağlam değişiminin bu durumda herhangi bir şeyi nasıl bozacağını anlamıyorum. Başka cevapların olmaması nedeniyle bunu kabul edilir olarak ayarlıyorum. – zeus

İlgili konular