这是我之前问题的后续。评论中指出,toRight回报Product with Serializable with scala.util.Either:
scala> val ox = Some(0)
ox: Some[Int] = Some(0)
scala> ox.toRight("No number")
res0: Product with Serializable with scala.util.Either[String,Int] = Right(0)
Run Code Online (Sandbox Code Playgroud)
现在我想知道它与我需要的类型有何不同Either。我应该Either[String,Int]这样明确添加吗?
scala> ox.toRight("No number"): Either[String, Int]
res1: Either[String,Int] = Right(0)
Run Code Online (Sandbox Code Playgroud) 我正在尝试编写解释器的内部结构,并且出于人体工程学的目的,我想我想要一个 monad 既可以像 state 一样工作,也可以像任何 monad 一样工作。
例如,我想用这两种风格做一些事情:
checkedAddress :: Integer -> Interpreter Int
checkedAddress n = if (n < toInteger (minBound :: Int))
then fail $ "Address " ++ show n ++ " is too low"
else if (n > toInteger (maxBound :: Int))
then fail $ "Address " ++ show n ++ " is too high"
else return $ fromInteger n
Run Code Online (Sandbox Code Playgroud)
我想用状态风格做其他事情:
setInstructionPointer :: Int -> Interpreter ()
setInstructionPointer ip (Machine _ mem) = ((), Machine ip …Run Code Online (Sandbox Code Playgroud) 我试图验证RecordwithApplicatives和Either Monad. 它工作正常。但我看不到所有错误消息。只有第一个是可见的,因为RightPathEither Monad忽略了它们。
这是我的代码:
import Data.Either (either)
import Text.Printf (printf)
data Record = Record
{ fieldA :: String
, fieldB :: String
, fieldC :: String
} deriving (Show, Eq)
type Err = String
setField :: String -> String -> Either Err String
setField field value
| length value > 0 = Right value
| otherwise = Left $ printf "value for field %s is to short" field
setFieldA …Run Code Online (Sandbox Code Playgroud) 我目前在理解 Haskell 中的任一种单子时遇到问题。两者都是 Monad 数据类型的实例。因此,我可以像这样在 Do 块中使用任一...
type MyAccount = Integer
transaction :: Integer -> MyAccount -> Either String MyAccount
transaction value account | value + account < 0 = Left "Error: insufficient funds!"
| otherwise = return $ account + value
Test1 :: Either String MyAccount
Test1 = do
account_state <- return 1000
r1 <- transaction (-200) account_state
r2 <- transaction (-1000) r1
return r2
Run Code Online (Sandbox Code Playgroud)
这是代码的工作片段:account_state、r1 和 r2是整数类型。因此函数事务正常工作。然而..
Test2 :: Either String MyAccount
Test2 = …Run Code Online (Sandbox Code Playgroud) 考虑以下函数:
validateList :: (a -> Either e a) -> [a] -> Either e [a]
validateList validate [] = Right []
validateList validate (x:xs) =
case validate x of
Left err -> Left err
Right y -> case validateList validate xs of
Left err -> Left err
Right ys -> Right $ y:ys
Run Code Online (Sandbox Code Playgroud)
有没有办法以更简洁的方式写这个?也许使用>>=运算符?
需要考虑一下,因为这里实际上有两个 monad:[]和Either,虽然List这里不充当 monad,但更多的是充当Traversable
有没有办法以更“单子”的方式编写这个函数,而不是诉诸于模式匹配Either?
{-# LANGUAGE LambdaCase #-}
calculate :: (Monad m) => (a -> m (Either e b)) -> Either e a -> m (Either e b)
calculate f = \case
Left err -> return $ Left err
Right vals -> f vals
Run Code Online (Sandbox Code Playgroud)
具体来说,对于我的用例来说,m是IO;f是一个函数,它接受输入并产生一些IO效果或失败的函数,而输入可能已经失败了。
也许使用ExceptT?
不知道该怎么称呼它,选择适合和任何一个,我需要处理第三种情况,无论如何.
Scalaz可能已经提供了这样的东西,但我很想知道如果没有单独的库,可以简洁地处理以下简单的情况:
我需要检查用户会话是否存在,包括实际用户和管理员登录用户方案,后者优先于前者; 如果两个条件都不存在,则显示登录屏幕
实际的用户会话检查如下所示:
request.session.get(Security.username) map { id=>
f(Success(id.toInt, request))
} getOrElse( onFail(request) ) // onFail = show login
Run Code Online (Sandbox Code Playgroud)
我需要在管理模拟用户案例中添加:
request.session.get(Security.impersonate) map { id=>
f(Success(id.toInt, request))
} getOrElse( onFail(request) )
Run Code Online (Sandbox Code Playgroud)
我可以将它们全部放在一起,但更愿意清理一下,无论用户或管理员用户情况如何,操作都是相同的.
如何将Eithers列表更改为右侧和左侧两个值列表.当我使用partition它时,返回两个不是值的列表.最简单的方法是什么?
我有一个输入值列表
List[A]
Run Code Online (Sandbox Code Playgroud)
和一个功能
f(List[A]): Either[Failure, Success]
Run Code Online (Sandbox Code Playgroud)
我将该函数应用于列表的每个元素,从而产生一个List[Either[Failure, Success]].
我想检查列表,如果任何值失败,则返回第一个失败,否则返回成功列表.
我使用了以下模式:
val allValues = list.map(f(_))
if (allValues.exists(_.isLeft)) {
allValues.find(_.isLeft).get
} else {
allValues.collect {
case Right(result) => result
}
}
Run Code Online (Sandbox Code Playgroud)
和
val allValues = list.map(f(_))
val failures = allValues.collect { case Left(error) => error }
if (failures.nonEmpty) {
failures(0)
} else {
allValues.collect {
case Right(result) => result
}
}
Run Code Online (Sandbox Code Playgroud)
是否有更简洁的方式来表达这种模式?
有时,我必须通过另一个函数进一步处理成功,再次使用相同的模式.例如
我想在REPL中创建一个Either使用实例asRight:
import cats._
import cats.data._
import cats.implicits._
scala> val x = "xxx".asRight
<console>:20: error: value asRight is not a member of String
val x = "xxx".asRight
^
scala> import cats.syntax.either._
import cats.syntax.either._
scala> val x = "xxx".asRight
<console>:23: error: value asRight is not a member of String
val x = "xxx".asRight
^
Run Code Online (Sandbox Code Playgroud)
上面的代码有什么问题?可以asRight在REPL中使用吗?