Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Scala 在哪里处理monad故障?_Scala_Haskell - Fatal编程技术网

Scala 在哪里处理monad故障?

Scala 在哪里处理monad故障?,scala,haskell,Scala,Haskell,我想知道使用monad编写代码的最佳方法是什么(可选,也可以尝试)。 我的第一印象是,那些单子应该让我写逻辑并忽略错误,然后根据类型结果我会更好地知道发生了什么。 我会举一个例子 val a:Option[Something] = list.get("key") 现在我可以像使用map和flatMap一样操作我的值 在代码末尾,如果我没有,则表示列表没有“键”。 只有当您的逻辑很小时,此工作流才起作用。 但是如果我有很多逻辑,我应该如何编写代码呢 i、 e: 现在,在处理错误时,我将执行以下操

我想知道使用monad编写代码的最佳方法是什么(可选,也可以尝试)。 我的第一印象是,那些单子应该让我写逻辑并忽略错误,然后根据类型结果我会更好地知道发生了什么。 我会举一个例子

val a:Option[Something] = list.get("key")
现在我可以像使用map和flatMap一样操作我的值
在代码末尾,如果我没有,则表示列表没有“键”。 只有当您的逻辑很小时,此工作流才起作用。 但是如果我有很多逻辑,我应该如何编写代码呢 i、 e:

现在,在处理错误时,我将执行以下操作:

processedValueOption match { 
   case None=> .... // server is not identified
   case Some(Failure(e)) =>  //error to get value from server
   case .......
}
实际上,我的类型让我知道代码末尾的错误是什么。 但是当你有大的逻辑时,它会变得非常复杂。
你认为我应该怎么写代码?当我编写逻辑以获得简单类型时,是否应该处理错误?

对于此类情况,这两种方法都是更好的解决方案之一

// Explicit errors
object MyErrors {
    trait MyError
    object ServerNotIdentifiedError extends MyError
    object CanNotGetValueFromServerError extends MyError
    object ValueProcessingFailedError extends MyError 
}

val server: Either[ Server, MyError ] = serverList.get("serverId").match {
  case Some( server ) => Left( server )
  case None => Right( ServerNotIdentifiedError )
}

// assuming getDataFromServer returns Try[ Value ]
val value:Either[ Value, MyError ] = getDataFromServer( serverId ) match {
  case Success( value ) => Left( value ),
  case Failure( ex ) => {
    ex.printStackTrace();
    Right( CanNotGetValueFromServerError )
  }  
}

// assuming processValue returns Try[ OtherValue ]
val processedValue: Either[ OtherValue, MyError ] = value match {
  case Left( value ) => processValue(value) match {
    case Success( otherValue ) => Left( otherValue )
    case Failure( ex ) => {
      ex.printStackTrace()
      Right( ValueProcessingFailedError )
    }
  }
  case _ => value
}

在Haskell中,这通常是通过
EitherT或
ExceptT
来实现的(
EitherT和
ExceptT
是单变量变压器,几乎相同)。您可以将
do
符号与这些符号中的任何一个一起使用,将可能失败的操作串在一起,并获得最终结果或有关失败的信息。在某些情况下,使用
Applicative
操作符可以更好。比如说,

f <$> e1 <*> e2 <*> e3

检查Haskell“errors”包可能很有价值:。通常你也应该用flatMap替换对map的调用。如果你使用flatMap,你不知道错误是什么,例如list1.get(key1).flatMap(key=>list2.get(key))。如果没有,你不知道为什么没有,是因为list1还是list2吗?如果你能给我完整的例子,那就太好了!我很高兴看到这一点。它还可以让我了解为什么以及在哪里使用Applicativegood思想,但我想你已经被惯例、左代表错误、右代表成功所迷惑了是的。。。惯例。。。我们应该遵循惯例。。。但我喜欢做相反的事情,因为印度的道路是左侧行驶的,所以对我来说右侧感觉像是错误的道路。
f <$> e1 <*> e2 <*> e3
f <$> e1 <*> (e2 <|> e3)