我尝试使用 IO [String]
绑定将 [String]
转换为<-
;但是,我需要使用do
块在where
语句下执行此操作,但Haskell一直抱怨缩进。这是代码:
decompEventBlocks :: IO [String] -> IO [[String]]
decompEventBlocks words
| words' /= [] = block : (decompEventBlocks . drop $ (length block) words')
| otherwise = []
where
do
words' <- words
let block = (takeWhile (/="END") words')
这是什么原因?我们如何在 do
声明中使用 where
块?此外,我们是否有机会在警卫面前发表一些声明?
答案 0 :(得分:5)
您无法将转换为IO字符串
。然而,您可以做的是将IO String的内容绑定到'变量',但这仍然会导致整个计算嵌入到IO中。
try
{
var host = BuildWebHost(args);
using (var scope = host.Services.CreateScope())
{
var services = scope.ServiceProvider;
try
{
var context = services.GetRequiredService<myContext>();
DbInitializer.Seed(context);
}
catch
{
throw;
}
}
host.Run();
}
catch
{
throw;
}
回答你的问题
foo = do
x <- baz -- here baz is the IO String
let x' = doStuff x
return x' -- embeds the String inside IO, as otherwise the computation would result in IO ()
答案 1 :(得分:4)
请记住:do
- 对于monadic表示法,块为syntactic sugar。这意味着以下情况适用:
do {a; b} = a >> b
dp {a <- b; c} = b >>= \a -> c
换句话说,当使用do
- 表示法时,实际上是在生成值。这就是为什么你不能在do
语句的顶层有一个where
块。
解决这个问题的方法是将函数放入do
- 块:
decompEventBlocks :: IO [String] -> IO [[String]]
decompEventBlocks words = do
-- We unwrap the IO [String], but we keep it in the do-block,
-- because it must be kept in a monadic context!
words' <- words
let block = (takeWhile (/="END") words')
-- This is equivalent to the guards you had in your function.
-- NB return :: Monad m => a -> m a, to keep it in a monadic context!
if not $ null words'
then do
-- Since the recursion is monadic, we must bind it too:
rest <- decompEventBlocks $ return $ drop (length block) words'
return $ block : rest
else return []
要了解monad,do
- 符号,>>=
和>>
,我强烈推荐阅读the LYAH chapters,以便在尝试更多monadic代码之前获得良好的理解。< / p>
答案 2 :(得分:0)
作为AJFarmar答案的一个略微不同的角度:Caused by: java.lang.IllegalArgumentException: org.hibernate.hql.internal.ast.QuerySyntaxException: Person is not mapped [select p from Person p]
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:131)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:155)
at org.hibernate.internal.ExceptionConverterImpl.convert(ExceptionConverterImpl.java:162)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:662)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:678)
at org.hibernate.internal.AbstractSessionImpl.createQuery(AbstractSessionImpl.java:23)
at models.JPAPersonRepository.list(JPAPersonRepository.java:48)
at models.JPAPersonRepository.lambda$null$2(JPAPersonRepository.java:35)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:142)
at play.db.jpa.DefaultJPAApi.withTransaction(DefaultJPAApi.java:100)
Caused by: org.hibernate.hql.internal.ast.QuerySyntaxException: Person is not mapped [select p from Person p]
at org.hibernate.hql.internal.ast.QuerySyntaxException.generateQueryException(QuerySyntaxException.java:79)
at org.hibernate.QueryException.wrapWithQueryString(QueryException.java:103)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.doCompile(QueryTranslatorImpl.java:218)
at org.hibernate.hql.internal.ast.QueryTranslatorImpl.compile(QueryTranslatorImpl.java:142)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:115)
at org.hibernate.engine.query.spi.HQLQueryPlan.<init>(HQLQueryPlan.java:77)
at org.hibernate.engine.query.spi.QueryPlanCache.getHQLQueryPlan(QueryPlanCache.java:153)
at org.hibernate.internal.AbstractSharedSessionContract.getQueryPlan(AbstractSharedSessionContract.java:545)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:654)
at org.hibernate.internal.AbstractSharedSessionContract.createQuery(AbstractSharedSessionContract.java:678)
中唯一的东西就是声明。 func switchCameraTapped() {
//Change camera source
//Indicate that some changes will be made to the session
session.beginConfiguration()
//Remove existing input
guard let currentCameraInput: AVCaptureInput = session.inputs.first else {
return
}
//Get new input
var newCamera: AVCaptureDevice! = nil
if let input = currentCameraInput as? AVCaptureDeviceInput {
if (input.device.position == .back) {
newCamera = cameraWithPosition(position: .front)
} else {
newCamera = cameraWithPosition(position: .back)
}
}
//Add input to session
var err: NSError?
var newVideoInput: AVCaptureDeviceInput!
do {
newVideoInput = try AVCaptureDeviceInput(device: newCamera)
} catch let err1 as NSError {
err = err1
newVideoInput = nil
}
if let inputs = session.inputs as? [AVCaptureDeviceInput] {
for input in inputs {
session.removeInput(input)
}
}
if newVideoInput == nil || err != nil {
print("Error creating capture device input: \(err?.localizedDescription)")
} else {
session.addInput(newVideoInput)
}
//Commit all the configuration changes at once
session.commitConfiguration()
}
// Find a camera with the specified AVCaptureDevicePosition, returning nil if one is not found
func cameraWithPosition(position: AVCaptureDevice.Position) -> AVCaptureDevice? {
let discoverySession = AVCaptureDevice.DiscoverySession(deviceTypes: [.builtInWideAngleCamera], mediaType: AVMediaType.video, position: .unspecified)
for device in discoverySession.devices {
if device.position == position {
return device
}
}
return nil
}
块不是声明,它们是表达式。即这与您尝试编写where
时的情况相同。如果您想在do
中声明where 2+5
,则必须
block
答案 3 :(得分:0)
使用表示法来编写一般表格的表达式
ex :: Monad m => m t
let ex = do
{ x <- foo -- foo :: Monad m => m a, x :: a
; y <- bar x -- bar x :: Monad m => m b, y :: b
; z <- baz x y -- baz x y :: Monad m => m c, z :: c
; quux x y z -- quux x y z :: Monad m => m t
}
请注意,所有m
都相同,而a
,b
,c
,...可能会有所不同,尽管t
位于最后执行子表达式的类型和整体 do 表达式的类型是相同的。
do 符号变量被称为&#34;绑定&#34;由<-
构造。它们在引入时(<-
的左侧)进入范围,并保留在所有后续 do 子表达式的范围内。
可用于任何monad的一个内置monadic表达式为return :: Monad m => a -> m a
。因此x <- return v
将 x
绑定到v
,以便x
在后续子表达式中可用,并且值为{ {1}}。
所有执行变量限制到 v
块,而不能在它外面使用。每个变量的范围都是同一do
块中的所有代码,位于变量绑定之下/之后。
这也意味着do
是非递归绑定,因为变量不能在右侧和左侧:它将是两个在这种情况下,具有相同名称的不同变量,并且必须在该点之上的某处建立右侧的变量。
这里有一些一般模式:
<-
所有do { _ <- p ; _ <- q ; r } === do { p ; q ; r }
do { x <- p ; return x } === do { p } === p
do { x <- return v ; foo x } === do { foo v } === foo v
do { p ; q ; r } === do { p ; do { q ; r } }
=== do { do { p ; q } ; r }
do { x <- p ; === do { x <- p ;
y <- q x ; z <- do { y <- q x ;
return (foo x y) } return (foo x y) } ;
return z }
表达式只是表达式,因此表达式尤其可以是Monad m => m a
表达式,其结果和备用分支具有相同的monadic类型(这通常令人困惑)初学者):
if - then - else
更新: monad的一个要点是它与纯计算的完全分离效果。一旦进入 monad,您就无法&#34;离开&#34; 。 Monadic计算可以使用纯计算,但反之亦然。