我希望获得一些有助于理解 Monad Transformers 的输入,以及与此相关的使用 do
表示法会发生什么。我试图理解的示例如下:
data ProtectedData a = ProtectedData String a
accessData :: String -> ProtectedData a -> Maybe a
accessData s (ProtectedData pass v) =
if s == pass then Just v else Nothing
type Protected s a = MaybeT (Reader (ProtectedData s)) a
-- untangles the monad construction
run :: ProtectedData s -> Protected s a -> Maybe a
run ps psa = runReader (runMaybeT psa) ps
access :: String -> Protected a a
access pass = do
-- ask :: ReaderT (ProtectedData a) Identity (ProtectedData a)
-- lift :: ... -> MaybeT (ReaderT (ProtectedData a) Identity) (ProtectedData a)
pd <- lift ask
-- as i understand it: ask returns the value inside the thing.
-- the left arrow actually applies the monad
let v = accessData pass pd
-- return :: Maybe a -> Reader (ProtectedData a) (Maybe a)
MaybeT $ return v
据我了解,Protected
类型描述了一些protected 数据,这些数据存储在共享环境 (Reader
) 中并且属于也许(MaybeT)
。
我在类型变量 s
和 a
方面遇到问题:
s
是否描述了 protected 数据的字符串(密码),a
protected 数据的类型?s
是否描述了 protected 数据的类型,如果是,是什么一个
描述?
在函数运行中:
run :: ProtectedData s -> Protected s a -> Maybe a
run ps psa = runReader (runMaybeT psa) ps
据我了解,Protected
中的 Reader
在 ProtectedData
上运行,以返回值。
这只留下函数access
:
access :: String -> Protected a a
access pass = do
pd <- lift ask
let v = accessData pass pd
MaybeT $ return v
最让我头疼的是哪个。首先,我在把握效果和结果方面遇到了问题。
- 此函数是否用于将密码和数据注入(inject)
Reader
? - 是否用于访问数据并在输入错误密码时失败?
其次我无法理解第一行
pd <- lift ask
- 我明白,
ask
用于访问共享环境 通过Reader
,但为什么我必须将它lift
到MaybeT
才能获得 它里面的实际值(value)?
最佳答案
As i understand it the Protected type describes some "protected" Data
没有。 Protected s a
应被视为返回类型 a
值的程序 类型。在计算过程中,程序对 s
类型的 secret 值具有只读访问权限,并且只有当它“知道”正确的密码时。
这样的 secret 值,与其密码配对,类型为ProtectedData s
。
does s describe the type of the protected Data, and if so, what does a describe?
是的。这里 a
是程序结果的通用类型。
举个例子,你可以考虑密码是 String
的情况(它必须是,在你的代码中字符串类型是硬编码的)并且 secret 值的类型是 s = 整数
。然后您编写一个访问 secret 整数的程序,并检查它是否为正数,并返回一个 Bool
。这里,a = Bool
。
请注意,我稍微简化了场景。由于我们还使用了 MaybeT
,因此我们正在对一个程序建模,该程序并不总是返回 a
类型的值,但也可能会失败。使用错误的密码可能会导致失败。在这种情况下,MaybeT
会在执行过程中粗略地中止程序。
签名
access :: String -> Protected a a
如果我们把它写成可能会更好理解
access :: String -> Protected s s
显示它是一个帮助函数来访问 secret 值(或失败),给定密码尝试。它的用法如下:
myProg :: Protected Int Bool
myProg = do
v <- access "123456" -- try accessing the protected int
return (v > 0)
如果密码错误,上面的代码会导致失败(run
会返回Nothing
)
> run (ProtectedData "actual password" 42) myProg
Nothing
如果密码正确,它会产生正确的 bool 值:
> run (ProtectedData "123456" 42) myProg
Just True
此处Just
表示密码正确,True
表示 protected Int
为正。
关于haskell - 理解 Monad 变形金刚的困难,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69063768/