2012-04-04 15 views
5

Kendimi bu kod yazmadan buldum çünkü monad transformatörlerin bazı temel anlayış eksik düşünüyorum: Bu çalışırArtışı hatası değeri

import Control.Monad.Identity 
import Control.Monad.Error 

liftError :: Either String Int -> ErrorT String Identity Int 
liftError x = do case x of 
        Right val -> return val 
        Left err -> throwError err 

gateway :: Bool -> ErrorT String Identity Int 
gateway = liftError . inner 

inner :: Bool -> Either String Int 
inner True = return 5 
inner False = throwError "test" 

, ben bu daha yapılabilir olduğunu düşünüyorum zarif. Özellikle, kendim tanımlamak zorunda olmamam gerektiğini düşündüğüm liftError'un yerini arıyorum.

gateway ve inner'u türlerini değiştirmeden birlikte çalışmanın en kolay yolu ne olurdu?

cevap

6

Sadece türlerini biraz değiştirirseniz, hiç bir kaldırma yapmanız gerekmez.

{-# LANGUAGE FlexibleContexts #-} 

gateway :: Bool -> ErrorT String Identity Int 
gateway = inner 

inner :: MonadError String m => Bool -> m Int 
inner True = return 5 
inner False = throwError "test" 

MonadErrorErrorT ve Either ikisi için örnekleri vardır, bu nedenle bu yolu hem de inner kullanabilirsiniz.

+0

Tamam, daha spesifik olmak gerekirse, türleri oldukları gibi bırakmak istesem elle kaldırma fonksiyonu yazmam gerekiyor mu? Bu sadece benim anlayışım içindir. BTW maalesef şu an için oy kullanamıyorum:/Yarınki oyu alacaksın :) –

+1

Türleri değiştirmeden 'ErrorT'yi kullanabilirsiniz. 'liftError' işlevinin yerine dön. Daha genel bir sürümü dahili olarak da kullanabilir ve yalnızca "iç" in bir kopyasını kısıtlanmış türde gösterebilirsiniz. – hammar

+0

Bu 'Hatalı. dönüş 'tam olarak aradığım şeydi. Bahsettiğim gibi, bu herhangi bir gerçek kod ile ilgisi yok, sadece monad transformatörleri kavramını anlamak istiyorum :) –

İlgili konular