定义新的 monad 实例
defining new monad instance
几天前,我试图通过创建一个新的 monad 实例来证明 monad 法则,但我发现自己陷入了定义新 monad 实例的困境。
{-# LANGUAGE DeriveFunctor, InstanceSigs #-}
import Control.Monad
newtype Test a = Test { getTest :: [Maybe a] }
deriving Functor
instance Applicative Test where
pure = return
(<*>) = liftM2 ($)
instance Monad Test where
return :: a -> Test a
return a = Test $ [Just a]
(>>=) :: Test a -> (a -> Test b) -> Test b
g >>= f = concat (map f g) --Tried to do something like this
我在列表 monad 定义之后尝试了一些东西,但是因为 concat 期望 [[a]] 而卡住了,但在这里它得到了 [Test b],所以也许还有其他可用的函数或者有没有办法让 concat 工作在新类型上?任何建议表示赞赏。谢谢
与 type
别名不同,newtype
包装器需要手动应用和删除。将 g >>= f = concat (map f g)
替换为 Test g >>= f = Test $ concat (map (getTest . f) g)
.
这只会给您留下一个类型错误:g
的类型是 [Maybe a]
而不是所需的 [a]
。我们可以添加一个 catMaybes
(需要 import Data.Maybe
)来解决这个问题:Test g >>= f = Test $ concat (map (getTest . f) $ catMaybes g)
。现在可以编译了。
不幸的是,这种情况是不合法的。我将把它留作 reader 的练习,以确定为什么不可以,以及它是否可以轻松修复。
它们可以是derived the the MaybeT []
transformer:
{-# Language DerivingVia #-}
{-# Language StandaloneKindSignatures #-}
import Control.Applicative (Alternative)
import Control.Monad (MonadPlus)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Trans.Maybe (MaybeT(..))
import Control.Monad.Zip (MonadZip)
import Data.Kind (Type)
type Test :: Type -> Type
newtype Test a = Test { getTest :: [Maybe a] }
deriving (Functor, Foldable, Applicative, Alternative, Monad, MonadFail, MonadFix, MonadPlus, MonadZip)
via MaybeT []
>> :instances MaybeT []
instance [safe] GHC.Base.Alternative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Applicative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Functor (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Monad (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] GHC.Base.MonadPlus (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Eq1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Foldable (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Ord1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Read1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Show1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Traversable (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] MonadFail (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Control.Monad.Fix.MonadFix (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Control.Monad.Zip.MonadZip (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Monad (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Applicative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Functor (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
其中一些实例也可以通过 Compose [] Maybe
but famously monads don't compose. :instances Compose [] Maybe
:
派生
>> :instances Compose [] Maybe
instance Alternative (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Applicative (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Functor (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Foldable (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Eq1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Ord1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Read1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Show1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Traversable (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Alt (Compose [] Maybe) -- Defined in ‘Data.Functor.Alt’
instance Hashable1 (Compose [] Maybe)
-- Defined in ‘hashable-1.3.0.0:Data.Hashable.Class’
几天前,我试图通过创建一个新的 monad 实例来证明 monad 法则,但我发现自己陷入了定义新 monad 实例的困境。
{-# LANGUAGE DeriveFunctor, InstanceSigs #-}
import Control.Monad
newtype Test a = Test { getTest :: [Maybe a] }
deriving Functor
instance Applicative Test where
pure = return
(<*>) = liftM2 ($)
instance Monad Test where
return :: a -> Test a
return a = Test $ [Just a]
(>>=) :: Test a -> (a -> Test b) -> Test b
g >>= f = concat (map f g) --Tried to do something like this
我在列表 monad 定义之后尝试了一些东西,但是因为 concat 期望 [[a]] 而卡住了,但在这里它得到了 [Test b],所以也许还有其他可用的函数或者有没有办法让 concat 工作在新类型上?任何建议表示赞赏。谢谢
与 type
别名不同,newtype
包装器需要手动应用和删除。将 g >>= f = concat (map f g)
替换为 Test g >>= f = Test $ concat (map (getTest . f) g)
.
这只会给您留下一个类型错误:g
的类型是 [Maybe a]
而不是所需的 [a]
。我们可以添加一个 catMaybes
(需要 import Data.Maybe
)来解决这个问题:Test g >>= f = Test $ concat (map (getTest . f) $ catMaybes g)
。现在可以编译了。
不幸的是,这种情况是不合法的。我将把它留作 reader 的练习,以确定为什么不可以,以及它是否可以轻松修复。
它们可以是derived the the MaybeT []
transformer:
{-# Language DerivingVia #-}
{-# Language StandaloneKindSignatures #-}
import Control.Applicative (Alternative)
import Control.Monad (MonadPlus)
import Control.Monad.Fix (MonadFix)
import Control.Monad.Trans.Maybe (MaybeT(..))
import Control.Monad.Zip (MonadZip)
import Data.Kind (Type)
type Test :: Type -> Type
newtype Test a = Test { getTest :: [Maybe a] }
deriving (Functor, Foldable, Applicative, Alternative, Monad, MonadFail, MonadFix, MonadPlus, MonadZip)
via MaybeT []
>> :instances MaybeT []
instance [safe] GHC.Base.Alternative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Applicative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Functor (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Monad (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] GHC.Base.MonadPlus (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Eq1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Foldable (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Ord1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Read1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Data.Functor.Classes.Show1 (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Traversable (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] MonadFail (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Control.Monad.Fix.MonadFix (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Control.Monad.Zip.MonadZip (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Monad (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Applicative (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
instance [safe] Functor (MaybeT [])
-- Defined in ‘Control.Monad.Trans.Maybe’
其中一些实例也可以通过 Compose [] Maybe
but famously monads don't compose. :instances Compose [] Maybe
:
>> :instances Compose [] Maybe
instance Alternative (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Applicative (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Functor (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Foldable (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Eq1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Ord1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Read1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Show1 (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Traversable (Compose [] Maybe)
-- Defined in ‘Data.Functor.Compose’
instance Alt (Compose [] Maybe) -- Defined in ‘Data.Functor.Alt’
instance Hashable1 (Compose [] Maybe)
-- Defined in ‘hashable-1.3.0.0:Data.Hashable.Class’