我有一个可变函数类型系列:
type family (~~>) (argTypes :: [Type]) (result :: Type) :: Type where
'[] ~~> r = r
(t ': ts) ~~> r = t -> (ts ~~> r)
infixr 0 ~~>
我想要一个可变参数函数,它将一些monadic动作(比如print)应用于它的所有参数:
class Foo (ts :: [Type]) where
foo :: ts ~~> IO ()
instance Foo '[] where
foo = pure ()
instance (Show t, Foo ts) => Foo (t ': ts) where
foo t = print t >> foo @ts
通常的monadic组合在这里不起作用。
(>>)
的类型为IO () -> IO () -> IO ()
。我需要使用IO () -> (ts ~~> IO ()) -> ts ~~> IO ()
类型的内容来组合print t
和foo @ts
。
是否可以编写这样的功能?
答案 0 :(得分:3)
延续传递风格可直接访问计算结果。
另一种方法是构建一个类型类来迭代合成,但它很麻烦。
{-# LANGUAGE FlexibleInstances #-}
class Foo t where
foo_ :: (IO () -> IO ()) -> t
instance (Show a, Foo t) => Foo (a -> t) where
foo_ k a = foo_ (\continue -> k (print a >> continue))
instance Foo (IO ()) where
foo_ k = k (return ())
foo :: Foo t => t
foo = foo_ id
main :: IO ()
main = foo () (Just "bar") [()]
答案 1 :(得分:0)
我找到了编写函数Sub EventRequests()
Dim ns As Outlook.NameSpace
Dim moveToFolder As Outlook.MAPIFolder
Dim objItem As Outlook.MailItem
Set ns = Application.GetNamespace("MAPI")
On Error GoTo 0
Set moveToFolder = ns.GetDefaultFolder(olFolderInbox).Parent.Folders("Events").Folders("Event Requests")
If Application.ActiveExplorer.Selection.Count = 0 Then
MsgBox ("Select an E-mail first")
Exit Sub
End If
If moveToFolder Is Nothing Then
MsgBox "Target folder not found!", vbOKOnly + vbExclamation, "Move Macro Error"
End If
For Each objItem In Application.ActiveExplorer.Selection
If moveToFolder.DefaultItemType = olMailItem Then
If objItem.Class = olMail Then
objItem.Move moveToFolder
End If
End If
Next
Set objItem = Nothing
Set moveToFolder = Nothing
Set ns = Nothing
End Sub
IO () -> (ts ~~> IO ()) -> ts ~~> IO ()
因此,有问题的实例成为:
-- | Perform first action `m a` then pass its result to a function `(a -> ts ~~> mb)`
-- which returns variadic function and return that function.
class BindV (m :: Type -> Type) a b (ts :: [Type]) where
bindV :: m a -> (a -> ts ~~> m b) -> ts ~~> m b
instance (Monad m) => BindV m a b '[] where
bindV ma f = ma >>= f
instance (BindV m a b ts) => BindV m a b (t ': ts) where
bindV ma f x = bindV @m @a @b @ts ma ((flip f) x)
-- | Monadic composition that discards result of the first action.
thenV :: forall (m :: Type -> Type) a b (ts :: [Type]).
(BindV m a b ts) =>
m a -> (ts ~~> m b) -> ts ~~> m b
thenV ma f = bindV @m @a @b @ts ma (\_ -> f)
我希望我可以将instance (Show t, Foo ts, BindV IO () () ts) => Foo (t ': ts) where
foo t = thenV @IO @() @() @ts (print t) (foo @ts)
和thenV
写为运算符,但bindV
不能与运算符一起使用。