繁体   English   中英

函数类型的适用实例和Monad实例?

[英]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 aString生成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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM