هاسكل: Lift vs Liftio
-
29-09-2019 - |
سؤال
في ما يجب أن تكون المواقف liftIO
يستخدم؟ عندما أستخدم ErrorT String IO
, ، ال lift
تعمل الوظيفة على رفع تصرفات IO إلى ErrorT
, ، لذا liftIO
يبدو غير ضروري.
المحلول
lift
يرفع دائمًا من الطبقة "السابقة". إذا كنت بحاجة إلى رفع من الطبقة الثانية ، فستحتاج lift . lift
وهلم جرا.
من ناحية أخرى، liftIO
يرفع دائمًا من طبقة IO (التي ، عند وجودها ، تكون دائمًا في أسفل المكدس). لذا ، إذا كان لديك أكثر من طبقتين من الموناد ، فستقدر liftIO
.
قارن نوع الوسيطة في Lambdas التالية:
type T = ReaderT Int (WriterT String IO) Bool
> :t \x -> (lift x :: T)
\x -> (lift x :: T) :: WriterT String IO Bool -> T
> :t \x -> (liftIO x :: T)
\x -> (liftIO x :: T) :: IO Bool -> T
نصائح أخرى
Liftio هو مجرد اختصار لموناد IO ، أيا كان الموناد الذي أنت فيه. في الأساس ، يساوي Liftio استخدام عدد متغير من المصاعد. في البداية ، قد يبدو هذا زائداً عن الحاجة ، لكن استخدام Liftio له ميزة واحدة كبيرة: إنه يجعل رمز IO الخاص بك Indpendent من بناء الموناد الفعلي حتى تتمكن من إعادة استخدام نفس الرمز بغض النظر عند كتابة محول موناد).
على يد Ohter ، لا يأتي Liftio مجانًا ، كما يفعل Lift: يجب أن يكون المحولات Monad التي تستخدمها الدعم لها ، على سبيل المثال ، يجب أن تكون الموناد مثالًا على فئة Monadio ، ولكن معظم الموناد في الوقت الحاضر (وبالطبع ، سيقوم محقق النوع بفحص هذا لك في وقت الترجم: هذه هي قوة Haskell!).