Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/jsf-2/2.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
Elm 不能从case语句中使用作为参数传递的可扩展记录参数的函数_Elm - Fatal编程技术网

Elm 不能从case语句中使用作为参数传递的可扩展记录参数的函数

Elm 不能从case语句中使用作为参数传递的可扩展记录参数的函数,elm,Elm,我试图使用可扩展记录从一些记录中提取一些信息。如果我创建了一个采用可扩展记录类型并返回字符串的函数,并在case语句中使用它,那么就没有问题了(namedToString,在下面的示例中)。但是,如果我尝试使用作为参数传递的函数(stringFromNamed),我将收到一个错误: This business value is a: Business But stringFromNamed needs the 1st argument to be: Named a ->

我试图使用可扩展记录从一些记录中提取一些信息。如果我创建了一个采用可扩展记录类型并返回字符串的函数,并在case语句中使用它,那么就没有问题了(
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
,这是一个具有相同签名的函数,它将成功,因此我不知道这是问题所在,或者如果是,那么我认为编译器应该能够解决我们想要的问题。