- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我希望能够多态地处理多个 Either
值(value)观相同的人 Left
类型,但不一样 Right
类型,例如:
foo = Left "foo" :: Either String Int
bar = Left "bar" :: Either String Char
list = [foo, bar]
Left
value 表示计算失败时的错误消息,而
Right
value 根据不同的计算有不同的类型。如果失败,我只关心收集左侧的错误,因此能够为此目的对所有错误进行相同处理会很有用。
* Couldn't match type `Char' with `Int'
Expected type: Either String Int
Actual type: Either String Char
* In the expression: bar
In the expression: [foo, bar]
In an equation for `list': list = [foo, bar]
经过大量搜索,我唯一偶然发现的是称为“部分类型签名”的东西,它使用“_”通配符,并且必须通过标志显式启用才能编译。但是,即使启用它,它似乎仍然没有任何改变:
foo = Left "foo" :: Either String Int
bar = Left "bar" :: Either String Char
list = [foo, bar] :: Either String _
我收到同样的错误:
* Couldn't match type `Char' with `Int'
Expected type: Either String Int
Actual type: Either String Char
* In the expression: bar
In the expression: [foo, bar] :: Either String _
In an equation for `list': list = [foo, bar] :: Either String _
在 Java 中(如果它有
Either
类型),我可以简单地做这样的事情:
List<Either<String, ?>> list = asList(foo, bar);
它会工作得很好,输入安全等等。
?
在 java ?如果不是,您如何处理您不关心某个类型变量并想对其进行抽象的情况?有替代方案吗?
Params
值,其中:
data Params = Params String Double Bool
为简单起见,我在上面的值构造函数中只包含了 3 个值,但实际上还有更多。
parse :: [String] -> Either [String] Params
parse args = if successful
then Right (Params strParam doubleParam boolParam)
else Left errors
where successful = null errors
(Right strParam) = eitherStr
(Right doubleParam) = eitherDouble
(Right boolParam) = eitherBool
errors = lefts [eitherStr, eitherDouble, eitherBool]
eitherStr = parseStr args
eitherDouble = parseDouble args
eitherBool = parseBool args
parseStr :: [String] -> Either String String
parseDouble :: [String] -> Either String Double
parseBool :: [String] -> Either String Bool
但它不能编译,因为我无法处理
eitherStr
,
eitherDouble
和
eitherBool
具有相同的类型,如果有通配符类型变量,这是可能的。因此我的问题。
parse :: [String] -> Either [String] Params
parse args = if successful
then Right (Params strParam doubleParam boolParam)
else Left errors
where successful = null errors
(Right strParam) = eitherStr
(Right doubleParam) = eitherDouble
(Right boolParam) = eitherBool
errors = concat [strErrors, doubleErrors, boolErrors]
strErrors = getErrors eitherStr
doubleErrors = getErrors eitherDouble
boolErrors = getErrors eitherBool
eitherStr = parseStr args
eitherDouble = parseDouble args
eitherBool = parseBool args
getErrors = lefts . (:[])
parseStr :: [String] -> Either String String
parseDouble :: [String] -> Either String Double
parseBool :: [String] -> Either String Bool
可行,但更麻烦。当然,我的解决方案可能完全偏离轨道,并且有更好的惯用功能解决方案,我会很高兴听到的。
Object
作为通用上限,因此比较具有误导性。但在我看来,理论上限总是存在的,即使在最坏的情况下,上限意味着您无法使用的值。这对于你不需要它的情况来说很好,比如我的。
Either
的函数不会接受新类型,也不能重用。所以不要使用现有的
lefts
函数,除了定义新类型的麻烦之外,我还必须自己为新类型实现它:
data SomeEither l = forall r. SomeEither (Either l r)
data Params = Params String Double Bool deriving (Show)
parse :: [String] -> Either [String] Params
parse args = if successful
then Right (Params strParam doubleParam boolParam)
else Left errors
where successful = null errors
(Right strParam) = eitherStr
(Right doubleParam) = eitherDouble
(Right boolParam) = eitherBool
errors = lefts' [SomeEither eitherStr, SomeEither eitherDouble, SomeEither eitherBool]
eitherStr = parseStr args
eitherDouble = parseDouble args
eitherBool = parseBool args
lefts' :: [SomeEither l] -> [l]
lefts' [] = []
lefts' ((SomeEither (Left l)):xs) = l:(lefts' xs)
lefts' (x:xs) = lefts' xs
parseStr :: [String] -> Either String String
parseDouble :: [String] -> Either String Double
parseBool :: [String] -> Either String Bool
重点是做更少的工作并拥有更干净的代码。在这种情况下,存在类型的使用正好相反。
最佳答案
这是徒劳的。 Either L R
哪里R
未知只是Maybe L
.如果您有 Right (r :: R)
并将其放入您的列表中,从而忘记了 R
是,那么即使你以后可以拿那个 Right r
出了列表,你将不知道 r
的类型.这使它无法使用。 Java 中也基本相同:a Either<L, ?>
真的只是一个 Optional<L>
.如果Either
是 Right
,好吧,你得到的只是一个 Object
(通配符的上限)。无视“万能”Object
Java 中的操作(最重要的是 instanceof
和 ==
,还有 equals
、 hashCode
、 wait
、 synchronized
等),这些都不存在(Haskell 运行时缺少身份值)类型),这个毫无特色的 Blob 你无能为力。为什么要把它放在首位?
现在,至于语法:_
Haskell 类型中的通配符是您不知道那里是什么类型的标记,并且您希望 GHC 推断它。我可以写:
something :: [a] -> _
something = foldr (:) []
GHC 会告诉我应该填写
_
与
[a]
,因为这是
something
的类型.
_
不允许任何“新的”;当您不知道某物的类型是什么但为了清楚起见而想将其写出时(或者当您不想写出类型时,因为它很大,但这种情况很少见),这只是一种便利。在您的情况下,
[foo, bar]
类型错误,句号。列表必须是同类的(包含相同类型的元素)并且
[foo, bar]
根本无效,并要求 GHC 告诉您当首先没有类型时该类型对您没有帮助。
?
类型是存在类型:
-- SomeEither l = Either<L, ?>
data SomeEither l = forall r. SomeEither (Either l r)
A
SomeEither l
(在 LHS 上声明)值是(根据 RHS)一对,由类型
r :: Type
组成和类型为
Either l r
的值.这也是
Either<L, ?>
的意思在 Java 中:
Either<L, ?>
是由类型
R
组成的对的类型(滥用 Java 术语,
R
是“捕获类型”)和值
Either<L, R>
.但是,在 Java 中,这些对的打包和解包是隐式的(打包称为“向上转换”,解包称为“通配符捕获”)。在 Haskell 中,你不得不说
list = [SomeEither foo, SomeEither bar]
但现在我们回到我的第一点,现在你永远不能使用
Right
再一次:
forM_ list (\(SomeEither x) ->
case x of
Left l -> putStrLn l
Right r -> putStrLn ":(") -- don't know type of r; can't really use it for anything!
因此,如果您必须在值进入列表之前对其进行预处理,并且如果没有必要保留
Right
周围的值,然后在开始时摆脱它们:
list :: [Maybe String]
list = [left foo, left bar]
where left = either Just (const Nothing)
-- or maybe you just want
list :: [String]
list = catMaybes [left foo, left bar]
where left = either Just (const Nothing)
编辑:“将东西放入列表”是 100% 不是您编辑的问题的解决方案。请注意,即使您有 Java 中的通配符类型,它们也无济于事。我想你真的想要这个
Applicative
(几乎是
WriterT [String] Maybe
):
newtype Validated a = Validated { runValidated :: Either [String] a }
deriving Functor
instance Applicative Validated where
pure = Validated . Right
Validated l <*> Validated r = Validated (l <!> r)
where
Left xs <!> Left ys = Left (xs ++ ys)
Left xs <!> Right _ = Left xs
Right _ <!> Left xs = Left xs
Right f <!> Right xs = Right (f xs)
parseStr :: [String] -> Validated String
parseDouble :: [String] -> Validated Double
parseBool :: [String] -> Validated Bool
parse :: [String] -> Validated Params
parse args = Params <$> parseStr args <*> parseDouble args <*> parseBool args
(遗憾的是,它不是
Monad
。)没有删除类型,没有什么花哨的。只需组合所有错误并在没有错误时生成一个值。
关于haskell - Haskell 中是否有通配符类型变量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64140299/
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE
谁能解释一下这个表达式是如何工作的? type = type || 'any'; 这是否意味着如果类型未定义则使用“任意”? 最佳答案 如果 type 为“falsy”(即 false,或 undef
我有一个界面,在IAnimal.fs中, namespace Kingdom type IAnimal = abstract member Eat : Food -> unit 以及另一个成功
这个问题在这里已经有了答案: 关闭 10 年前。 Possible Duplicate: What is the difference between (type)value and type(va
在 C# 中,default(Nullable) 之间有区别吗? (或 default(long?) )和 default(long) ? Long只是一个例子,它可以是任何其他struct类型。 最
假设我有一个案例类: case class Foo(num: Int, str: String, bool: Boolean) 现在我还有一个简单的包装器: sealed trait Wrapper[
这个问题在这里已经有了答案: Create C# delegate type with ref parameter at runtime (1 个回答) 关闭 2 年前。 为了即时创建委托(dele
我正在尝试获取图像的 dct。一开始我遇到了错误 The function/feature is not implemented (Odd-size DCT's are not implemented
我正在尝试使用 AFNetworking 的 AFPropertyListRequestOperation,但是当我尝试下载它时,出现错误 预期的内容类型{( “应用程序/x-plist” )}, 得
我在下面收到错误。我知道这段代码的意思,但我不知道界面应该是什么样子: Element implicitly has an 'any' type because index expression is
我尝试将 SignalType 从 ReactiveCocoa 扩展为自定义 ErrorType,代码如下所示 enum MyError: ErrorType { // .. cases }
我无法在任何其他问题中找到答案。假设我有一个抽象父类(super class) Abstract0,它有两个子类 Concrete1 和 Concrete1。我希望能够在 Abstract0 中定义类
我想知道为什么这个索引没有用在 RANGE 类型中,而是用在 INDEX 中: 索引: CREATE INDEX myindex ON orders(order_date); 查询: EXPLAIN
我正在使用 RxJava,现在我尝试通过提供 lambda 来订阅可观察对象: observableProvider.stringForKey(CURRENT_DELETED_ID) .sub
我已经尝试了几乎所有解决问题的方法,其中包括。为 提供类型使用app.use(express.static('public'))还有更多,但我似乎无法为此找到解决方案。 index.js : imp
以下哪个 CSS 选择器更快? input[type="submit"] { /* styles */ } 或 [type="submit"] { /* styles */ } 只是好
我不知道这个设置有什么问题,我在 IDEA 中获得了所有注释(@Controller、@Repository、@Service),它在行号左侧显示 bean,然后转到该 bean。 这是错误: 14-
我听从了建议 registering java function as a callback in C function并且可以使用“简单”类型(例如整数和字符串)进行回调,例如: jstring j
有一些 java 类,加载到 Oracle 数据库(版本 11g)和 pl/sql 函数包装器: create or replace function getDataFromJava( in_uLis
我已经从 David Walsh 的 css 动画回调中获取代码并将其修改为 TypeScript。但是,我收到一个错误,我不知道为什么: interface IBrowserPrefix { [
我是一名优秀的程序员,十分优秀!