- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有以下两个功能:
load :: Asset a => Reference -> IO (Maybe a)
send :: Asset a => a -> IO ()
class (Typeable a,ToJSON a, FromJSON a) => Asset a where
ref :: a -> Reference
...
a
应该是什么。 (
Could not deduce (Asset a0) arising from a use of 'load'
)
load
和
send
都是多态的。编译器必须以某种方式决定要使用哪个版本的
send
(并扩展为哪个版本的
toJSON
)。
a
的具体类型是什么。该信息实际上既编码在磁盘上的数据中,也编码在
Reference
类型中,但是我不确定在编译时正在运行类型检查器。
data Reference = Ref {
assetType:: String
, assetIndex :: Int
} deriving (Eq, Ord, Show, Generic)
reference :: Parser Reference
reference = do
t <- string "User"
<|> string "Port"
<|> string "Model"
<|> ...
char '-'
i <- int
return Ref {assetType = t, assetIndex =i}
Reference
添加类型参数,我只是将问题推回到解析器中。我仍然需要将在编译时不知道的字符串转换为可以完成此工作的类型。
最佳答案
您无法创建根据字符串中的内容将字符串数据转换为不同类型的值的函数。那根本不可能。您需要重新安排事情,以便您的返回类型不依赖于字符串内容。
您为load
输入的类型,Asset a => Reference -> IO (Maybe a)
说“选择您喜欢的任何a
(其中为Asset a
)并给我一个Reference
,然后我会给您发回一个产生IO
的Maybe a
动作。 ”。调用者通过引用选择他们希望加载的类型;文件的内容不影响加载的类型。但是,您不希望它被调用方选择,而是希望它被存储在磁盘上的内容选择,因此类型签名根本无法表达您实际想要的操作。那是你真正的问题;如果load
和send
分别正确,并且将它们组合在一起是唯一的问题,则将TypeApplications
和load
组合时的歧义类型变量将很容易解决(带有类型签名或send
)。
基本上,您不能只让load
返回多态类型,因为如果这样做,则调用方必须(必须)确定其返回的类型。有两种避免这种情况的方法,它们或多或少是等效的:返回一个存在的包装器,或使用等级2类型并添加一个多态处理程序函数(continuation)作为参数。
使用现有的包装器(需要GADTs
扩展名),看起来像这样:
data SomeAsset
where Some :: Asset a => a -> SomeAsset
load :: Reference -> IO (Maybe SomeAsset)
load
不再是多态的。您得到一个
SomeAsset
(就类型检查器而言)可以包含具有
Asset
实例的任何类型。
load
可以在内部使用它想要划分为多个分支的任何逻辑,并在不同分支上得出不同类型资产的值;如果每个分支都以
SomeAsset
构造函数包装资产值,则所有分支将返回相同的类型。
send
它,您将使用类似(忽略我不处理
Nothing
)的方法:
loadAndSend :: Reference -> IO ()
loadAndSend ref
= do Just someAsset <- load ref
case someAsset
of SomeAsset asset -> send asset
SomeAsset
包装器保证
Asset
保留其包装后的值,因此您可以将其拆开并在结果上调用任何
Asset
-polymorphic函数。但是,您永远无法以任何其他方式对依赖于特定类型的值进行任何操作1,这就是为什么必须始终将其包装起来并始终
case
对其进行匹配的原因;如果
case
表达式产生的类型取决于所包含的类型(例如
case someAsset of SomeAsset a -> a
),则编译器将不接受您的代码。
RankNTypes
并为
load
提供如下类型:
load :: (forall a. Asset a => a -> r) -> Reference -> IO (Maybe r)
load
完全不返回表示已加载资产的值。相反,它执行的是将多态函数作为参数。该函数可在任何
Asset
上工作并返回
r
类型(由
load
的调用者选择),因此
load
可以再次在内部分支,但可以根据需要在不同的分支中构造不同类型的资产。不同的资产类型都可以传递给处理程序,因此可以在每个分支中调用处理程序。
SomeAsset
方法,但随后也使用
RankNTypes
并定义一个辅助函数,例如:
withSomeAsset :: (forall a. Asset a => a -> r) -> (SomeAsset -> r)
withSomeAsset f (SomeAsset a) = f a
case
的任何地方都取消了
SomeAsset
语法:
loadAndSend :: Reference -> IO ()
loadAndSend ref
= do Just asset <- load ref
withSomeAsset send asset
sendSome = withSomeAsset send
Reference
,OP表示反对,只是指出将相同的问题移至构造引用时。如果参考文献包含代表其所指资产类型的数据,那么我强烈建议您采纳Daniel的建议,并使用此答案中描述的概念在参考文献构建级别解决该问题。
Reference
具有类型参数可以防止混淆对您确实知道类型的资产的错误引用。
Asset
暗含
Typeable
,因此您可以针对特定类型对其进行测试,然后将其返回。
关于haskell - 解决模糊类型变量,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51831989/
我正在尝试编写一个相当多态的库。我遇到了一种更容易表现出来却很难说出来的情况。它看起来有点像这样: {-# 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 { [
我是一名优秀的程序员,十分优秀!