Elm 不能从case语句中使用作为参数传递的可扩展记录参数的函数
我试图使用可扩展记录从一些记录中提取一些信息。如果我创建了一个采用可扩展记录类型并返回字符串的函数,并在case语句中使用它,那么就没有问题了(Elm 不能从case语句中使用作为参数传递的可扩展记录参数的函数,elm,Elm,我试图使用可扩展记录从一些记录中提取一些信息。如果我创建了一个采用可扩展记录类型并返回字符串的函数,并在case语句中使用它,那么就没有问题了(namedToString,在下面的示例中)。但是,如果我尝试使用作为参数传递的函数(stringFromNamed),我将收到一个错误: This business value is a: Business But stringFromNamed needs the 1st argument to be: Named a ->
namedToString
,在下面的示例中)。但是,如果我尝试使用作为参数传递的函数(stringFromNamed
),我将收到一个错误:
This business value is a:
Business
But stringFromNamed needs the 1st argument to be:
Named a -> String (edited)
从下面的示例代码:
type alias Named a =
{ a | name : String }
type alias Person =
Named { address : String }
type alias Business =
Named { employeeCount : Int }
type Change
= PersonUpdate Person
| BusinessUpdate Business
namedToString : Named a -> String
namedToString changeFields =
changeFields.name
changeToString : (Named a -> String) -> Change -> String
changeToString stringFromNamed change =
case change of
PersonUpdate person ->
-- This works
namedToString person
BusinessUpdate business ->
-- This will cause the error
stringFromNamed business
此示例仅包含所需的代码,但更完整的示例可在
问题的原因是什么?我如何才能实现传递一个函数的目标,该函数将从可扩展记录中提取一些信息?我认为问题在于,您传递的函数使用名为a的
,而Elm不知道a
指的是什么,因此它最终决定它是类型不匹配。如果将类型注释更改为(命名业务->字符串)->change->String
,它将编译并工作 我在Elm编译器repo中发现了这个问题:
这似乎是编译器中的一个bug,如果您只想将一种类型的外部记录传递给函数参数,可以解决这个bug。您可以通过删除上例中高阶函数的类型签名来完成此操作,changeToString
不幸的是,如果我们想从函数参数执行相同的操作,例如,stringfromname
,在每种情况下都会返回错误,因此必须找到另一种解决方法
我正在使用的解决方法是创建一个新的记录类型,它完全包括可扩展记录中的字段,然后从遵循可扩展记录类型的其他记录的字段中创建一个实例。只有几个案例和一个只有一个字段的可扩展记录并不是什么大问题,但这并不能很好地扩展。示例如下:
type alias Named a =
{ a | name : String }
type alias OnlyNamed =
Named {}
type alias Person =
Named { address : String }
type alias Business =
Named { employeeCount : Int }
type Change
= PersonUpdate Person
| BusinessUpdate Business
type Msg
= UpdateCurrentChange Change
namedToString : Named a -> String
namedToString changeFields =
changeFields.name
changeToString : (OnlyNamed -> String) -> Change -> String
changeToString stringFromNamed change =
case change of
PersonUpdate { name } ->
stringFromNamed { name = name }
BusinessUpdate { name } ->
stringFromNamed { name = name }
函数
stringFromNamed
在哪里定义?或者将什么作为函数param传递给changeToString
?检查上面链接中的扩展示例,但它甚至可能传递namedToString
,直接使用时有效,但作为参数传递时无效。哦,我一开始错过了调用部分。这些类型没有显式设置,因此可能会混淆Elm。或者类型不是您所期望的。我以前也遇到过类似的问题,但记不清具体的解决方案。您可以尝试定义一种在任何地方都使用的函数类型。因此,您的函数不使用(命名为a->String)
而是使用SomeFunctionType
,其中这是一个别名,别名为类型别名SomeFunctionType=(命名为a->String)
stringFromNamed
是一个参数,在展开的示例中,它是在调用changeToString
的第64行定义的。我已尝试按照您的建议为函数类型创建类型别名,但不幸的是,它似乎无法解决此问题。我已通过创建一条记录,其中包含Named
,type alias NamedItem={name:String}
中的字段,并构建此记录的新实例,从而解决了此问题(显式使用构造函数,如果不使用构造函数,似乎无法工作)让我以前使用名为a的函数现在使用名为
的函数。它可以工作,但有点混乱,似乎不符合语言的精神。我仍然想知道我是否做错了什么,或者是否有更好的方法来处理这个问题。如果我将行stringFromNamed business
更改为namedToString business
,这是一个具有相同签名的函数,它将成功,因此我不知道这是问题所在,或者如果是,那么我认为编译器应该能够解决我们想要的问题。