绑定到Haskell中数据结构内部的monad
有没有一种定义绑定的方法只影响数据结构的一部分 例如,假设我们有一个模拟计算数据类型,它有一个名称和一个结果绑定到Haskell中数据结构内部的monad,haskell,Haskell,有没有一种定义绑定的方法只影响数据结构的一部分 例如,假设我们有一个模拟计算数据类型,它有一个名称和一个结果 type Name = String data Error = TimeOut | NotEnoughMemory | DivByZero type Result a = Either Error a data Computation a = Computation Name (Result a) 由于计算可能会失败,但我们可能仍然对它的名称
type Name = String
data Error = TimeOut | NotEnoughMemory | DivByZero
type Result a = Either Error a
data Computation a = Computation Name (Result a)
由于计算可能会失败,但我们可能仍然对它的名称感兴趣,它不能是结果的一部分,必须是计算的一部分。另一方面,直接绑定和验证计算结果也很方便,就像使用常规类型一样。有办法吗?不,您可能无法定义任何有用的
实例Monad计算
,因为您无法从Applicative
类(它是Monad
的超类)中定义pure::a->Computation a
;如果只给a
类型的值,您将如何实例化名称
但它是一个函子
(您可以自动派生它)。有了更多的上下文,可能会有一个更有用的不同抽象。TW
我想你可能想要
type Computation = ExceptT Error (Writer Name)
-- in familiar types:
-- Computation a ⋍ (Either Error a, Name)
注意,Name
现在必须是Monoid
。这是有道理的,因为
liftA2 (+) comp1 comp2
,它添加了两个子计算的结果,还需要有一个名称。Writer
组件所做的是连接(使用monoid的
——因此不一定只是字符串连接)两个子计算的名称。例如,您可能会使用:
newtype Name = Name [String]
deriving (Semigroup, Monoid)
two :: Computation Int
two = name "two" $ pure 2
someComp :: Computation Int
someComp = name "two plus two" $ liftA2 (+) two two
您可能还需要一种方法来定义某些计算的名称:
name :: String -> Computation a -> Computation a
name n = mapExceptT (censor (const (Name [n])))
例如:
newtype Name = Name [String]
deriving (Semigroup, Monoid)
two :: Computation Int
two = name "two" $ pure 2
someComp :: Computation Int
someComp = name "two plus two" $ liftA2 (+) two two
假设您要绑定一个计算,那么输出
计算
应该有哪个名称
?使用return
生成的计算
应该有什么名称?计算
看起来只是将名称绑定到某个匿名计算的结果,而不是表示任何计算本身。