我正在编写一些lift
函数,这些函数采用记录字段函数,一些参数,然后lift
将记录中存储的操作Monad
转移到另一个liftCapability :: Has capability e
=> ( capability -> IO a )
-> ReaderT e IO a
liftCapability f = do
capability <- asks getter
lift $ f capability
,其中I&#39;我在工作:
lift
问题是,如果我需要使用更多参数调用它,我已经到达了一个我有很多liftCapability1 :: Has capability e
=> ( capability -> a -> IO b )
-> a
-> ReaderT e IO b
liftCapability1 f a = do
capability <- asks getter
lift $ f capability a
liftCapability2 :: Has capability e
=> ( capability -> a -> b -> IO c )
-> a
-> b
-> ReaderT e IO c
liftCapability2 f a b = do
capability <- asks getter
lift $ f capability a b
函数的地方,每个函数用于不同的arity:
curryN
有没有办法抽象出作为eta-reduce的函数的最后一个参数的应用?
到目前为止,我已尝试使用tuple package中的uncurryN
和liftC f =
liftC' f . curryN
where
liftC' f a = do
c <- asks getter
lift $ (f c) (uncurryN a)
,但这不起作用,因为它不能讨论少于两个参数:< / p>
'parent_id' => [
'type' => Form::INPUT_WIDGET,
'widgetClass' => '\kartik\widgets\Select2',
'options' => [
'data' => ArrayHelper::map(app\models\FinancialAccounts::find()
->all(), 'account_id', 'account_name'),
'options' => ['placeholder' => '...'],
'pluginOptions' => ['allowClear' => true],
]
],
这是可能的,还是我注定每个人都有一个功能?
答案 0 :(得分:0)
一种解决方案是更改您使用liftCapability
的功能的参数顺序。
λ :t \f b -> liftCapability $ \x -> f x b
\f b -> liftCapability $ \x -> f x b
:: Has t1 e => (t1 -> t2 -> IO a) -> t2 -> ReaderT e IO a
λ :t \f c b -> liftCapability $ \x -> f x c b
\f c b -> liftCapability $ \x -> f x c b
:: Has t1 e =>
(t1 -> t2 -> t3 -> IO a) -> t2 -> t3 -> ReaderT e IO a
另一个是使用类型类
{-# LANGUAGE FlexibleContexts, FlexibleInstances, MultiParamTypeClasses, TypeFamilies #-}
-- ...
class LiftableCapability v where
type Low v :: *
type Env v :: *
liftCapability :: Has capability (Env v) => (capability -> Low v) -> v
instance LiftableCapability (ReaderT e IO a) where
type Low (ReaderT e IO a) = IO a
type Env (ReaderT e IO a) = e
liftCapability f = lift . f =<< asks getter
instance LiftableCapability v => LiftableCapability (a -> v) where
type Low (a -> v) = a -> Low v
type Env (a -> v) = Env v
liftCapability f = liftCapability . flip f