我知道在do
区块内我可以从monadic中抽取“提取”其内容。例如,如果我有一个带签名的函数:
myFunction :: MyReader (Set Int)
我可以在do
块中执行此操作:
mySet <- myFunction
这会给我{I}我想要的Set Int
。但是,如果我改变我的功能以便它需要一个参数:
myFunction :: Int -> MyReader (Set Int)
我不能再做我想做的事了:
myFunction' <- myFunction
无法编译错误Couldn't match expected type
和Probable cause: ‘myFunction'’ is applied to too few arguments
。尝试这样的事情甚至在语法上都不正确:
myFunction' x <- myFunction x
我确实希望myFunction'
属于Int -> Set Int
类型。我无法弄清楚或找到任何地方如何做我想要的。有人可以帮忙吗?
答案 0 :(得分:1)
这可能是您正在寻找的:(未经测试)
data MyEnv = MyEnv { myFn :: Int -> Set Int }
type MyReader a = Reader MyEnv a
myFunction :: Int -> MyReader (Set Int)
something = do
...
myFunction' <- reader (\env x -> runReader (myFunction x) env)
-- here myFunction' :: Int -> Set Int
但是,它有点丑陋,因为它打破了抽象并重建它。也许有一种更清洁的方式,但由于在任意一元化中不可能做同样的事情,我们真的需要以某种方式打破抽象。
你至少可以将辅助细节保存在辅助函数中:
flipReader :: (a -> Reader b c) -> Reader b (a -> c)
flipReader r = reader (\y x -> runReader (r x) y)
然后:
something = do
...
myFunction' <- flipReader myFunction
答案 1 :(得分:0)
这将有效:
result <- myFunction x
基本上,myFunction
的类型为a -> MyReader b
,因此myFunction x
(其中x :: a
)的类型为MyReader b
。如您所知,您可以使用MyReader b
从<-
获取值,因此上面的表达式可以正常工作。
Haskell“do”符号是一种(非常松散地说)像一种简单的小脚本语言,你可以将“命令”链接在一起(再次,这是非常松散的),并将结果“存储”在“变量”中”
var1 <- command1
var2 <- command2 var1
可以读作
run command1, store the result in var1
then
run command2 using var1 as a parameter, store the result in var2
警告...
有许多monad这个类比会破坏,并且完全错误,但在早期,这几乎是初学者一段时间看到的唯一模式。