[英]Applicative and Monad instances for a function type?
我有一个类似于下面的Blah
的数据类型,但是由于这种类型的怪癖,我无法自动派生Functor,Applicative和Monad 。 因此,我必须手动执行此操作,但不确定如何操作。 我试图从((->) a)
的实例中汲取灵感,但是我不太清楚Monad实例。
newtype Blah a = Blah (String -> a) -- deriving (Functor, Applicative, Monad)
-- this seems right
instance Functor Blah where
fmap f (Blah g) = Blah (f . g)
instance Applicative Blah where
pure = Blah . const
-- This is right, right?
(<*>) (Blah f) (Blah g) = Blah $ \x -> f x (g x)
instance Monad Blah where
return = pure
-- I'm not having any luck here.
(>>=) a b = Blah $ \c -> _
编辑:有人将此标记为另一个的重复,但我不知道从哪里可以得到答案。 新型包装器使这变得困难。 在我写这个问题之前,我在(->) a
基础上查找了Monad
实例,但是答案中的体操正是我所需要的。
怎么样
Blah f >>= g = Blah $ \s ->
let Blah h = g $ f s in h s
您可以derive
这些实例。 您只需要打开GeneralizedNewtypeDeriving
标志,这将使GHC可以简单地将实例重新用于包装类型。
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Blah a = Blah (String -> a) deriving (Functor, Applicative, Monad)
这是您使用键入的孔自己得出此结果的方法。 从您的代码开始,重命名了一下:
instance Monad Blah where
return = pure
f >>= g = Blah $ \s -> _
您会收到这样的消息:
Found hole ‘_’ with type: b
Relevant bindings include
s :: String
g :: a -> Blah b
f :: Blah a
因此,我们需要制作b
,给定一个String
,一个Blah a
,以及a -> Blah b
。 好了,我们已经知道如何通过模式匹配和在Blah
应用该函数从Blah a
和String
生成a
:
Blah f >>= g = Blah $ \s -> let h = f s in _
------ -----------
现在我们得到:
Found hole ‘_’ with type: b
Relevant bindings include
h :: a
s :: String
g :: a -> Blah b
f :: String -> a
因此,我们有一个a
,我们可以将其赋予g
以获得Blah b
,然后进行模式匹配就可以得到一个Blah b
String -> b
:
Blah f >>= g = Blah $ \s -> let Blah h = g (f s) in _
----------------
现在我们得到:
Found hole ‘_’ with type: b
Relevant bindings include
h :: String -> b
s :: String
g :: a -> Blah b
f :: String -> a
所以我们需要一个b
,并且有一个String
和一个String -> b
。 这很容易:
Blah f >>= g = Blah $ \s -> let Blah h = g (f s) in h s
---
在类型的指导下,您可以找到正确的实现。 如果您定义帮助程序功能来“运行” Blah
您可能还会发现它更清晰:
newtype Blah a = Blah { runBlah :: String -> a }
-- or:
runBlah :: Blah a -> String -> a
runBlah (Blah f) = f
instance Monad Blah where
f >>= g = Blah $ \s -> runBlah (g (runBlah f s)) s
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.