你能让一个函数在Elm中使用多种类型吗?你有重载功能吗?

Con*_*ean 6 functional-programming overloading pattern-matching elm

我正在尝试从JS移植一个库,我已经找到了一个可以接受字符串或字符串列表的函数.如果给定一个字符串,它会将其拆分为一个字符串列表,然后继续,就好像它首先被传递一样.

我可以通过定义自己的类型来做到这一点,但它会使API变得丑陋,并且需要为数据添加自定义类型前缀.

这是我得到的:

type DocumentBody = Raw String | Words List String

tokenize: DocumentBody -> List String
tokenize s = 
    case s of
        Raw str_body -> String.split " " str_body |> (List.map String.toLower)
        Words list_body -> List.map String.toLower list_body

-- Tests

tests = 
    suite "Tokenizer"
    [ test "simple" <| assertEqual ["this", "is", "a", "simple", "string"]
                                   <| tokenize (Raw "this is a simple string")

    , test "downcasing tokens: string" <| assertEqual ["foo", "bar"]
                                                      <| tokenize (Raw "FOO BAR")

    , test "downcasing tokens: list of str" <| assertEqual ["foo", "bar"]
                                                           <| tokenize (Words ["Foo", "BAR"])
    ]
Run Code Online (Sandbox Code Playgroud)

最终,我不认为端口应该支持这种行为,但是如何在类型的枚举上模式匹配而不是需要前缀RawWords在我的示例中?

Cha*_*ert 5

不,您不能像使用其他语言一样以Elm重载函数。每个功能都有一个签名。如果您希望函数接受可以是多种类型的参数,则使用联合类型的解决方案就可以了。

您说它使API难看。我不会觉得丑陋。类型声明或case语句的语法可能并不吸引人,但我说,给它一点时间。它会在你身上成长。那里有很多电源和安全性。您不会让代码做任何假设,而是被迫处理每种情况,这是使用Elm之类的语言的优势之一。

您的模式匹配代码是合适的。您不能将其缩短到此以外。

同时,我可以理解重写JavaScript库并尝试通过原始JavaScript通过端口进行通信的痛苦。您正在用更严格的语言重写内容,并且您将无法复制使用javascript接受任何内容的函数签名。但这又是榆树的强项,而不是弱项。借此机会加强API并消除歧义。

对于您的特定示例,在我看来,您的解决方案之外还有其他可能的选择。我认为该tokenize功能从一开始就很有希望。这太含糊了。用功能语言编写代码时,我更喜欢使内容小巧且可组合。对我来说,它实际上应该是两个单独的功能,每个功能都有一个特定的目的。