如何从自定义类型的多个变体中提取值?

时间:2019-03-18 17:45:29

标签: pattern-matching elm algebraic-data-types

我有类似的类型

type Post 
    = Blog String String
    | Announcement String String

还有类似的功能

upcaseTitle : Post -> Post
upcaseTitle post =
    case post of
        Blog title body ->
            { post | title = String.toUpper title }
        Announcement title body ->
            { post | title = String.toUpper title }

我想写类似的代码

upcaseTitle : Post -> Post
upcaseTitle post =
    case post of
        Post title body ->
            { post | title = String.toUpper title }

我想在我的case语句中添加一个与所有Post类型匹配的子句,并提取公用的Stringtitle,因为它在我的工会类型。

榆树有可能吗?

1 个答案:

答案 0 :(得分:6)

不,不可能。在其他几种语言中,也可以使用or模式来实现(即使那样,您仍然必须枚举和解构每个变体,但是它们可以共享一个主体),但是Elm的目标是成为比这更简单的语言。

一种选择是将公共分支主体提取到一个函数中:

> install.packages("https://cran.r-    project.org/src/contrib/Archive/JohnsonDistribution/JohnsonDistribution_0.24.tar.gz", 
+                  repos = NULL)
trying URL 'https://cran.r-    project.org/src/contrib/Archive/JohnsonDistribution/JohnsonDistribution_0.2    4.tar.gz'
Content type 'application/x-gzip' length 7744 bytes
==================================================
downloaded 7744 bytes

* installing *source* package ‘JohnsonDistribution’ ...
** package ‘JohnsonDistribution’ successfully unpacked and MD5 sums checked
** libs
gfortran   -fPIC  -g -O2  -c JohnsonCurve.f -o JohnsonCurve.o
clang -dynamiclib -Wl,-headerpad_max_install_names -undefined     dynamic_lookup -single_module -multiply_defined suppress -    L/Library/Frameworks/R.framework/Resources/lib -L/usr/local/lib -o     JohnsonDistribution.so JohnsonCurve.o -L/usr/local/gfortran/lib/gcc/x86_64-    apple-darwin15/6.1.0 -L/usr/local/gfortran/lib -lgfortran -lquadmath -lm -    F/Library/Frameworks/R.framework/.. -framework R -Wl,-framework -    Wl,CoreFoundation
ld: warning: directory not found for option '-    L/usr/local/gfortran/lib/gcc/x86_64-apple-darwin15/6.1.0'
installing to     /Library/Frameworks/R.framework/Versions/3.5/Resources/library/JohnsonDistribution/libs
** R
** byte-compile and prepare package for lazy loading
** help
*** installing help indices
** building package indices
** testing if installed package can be loaded
* DONE (JohnsonDistribution)

另一种方法是定义一个单独的函数以仅提取标题:

upcaseTitle : Post -> Post
upcaseTitle post =
    let
        setTitle title =
            { post | title = String.toUpper title }
    in
    case post of
        Blog title body ->
            setTitle title

        Announcement title body ->
            setTitle title

但是,如果您的自定义类型的每个变体都相同,那么我将首先质疑该类型的设计。也许最好使用帖子类型只是字段的记录?

getTitle : Post -> String
getTitle post =
    case post of
        Blog title body ->
            title

        Announcement title body ->
            title

upcaseTitle : Post -> Post
upcaseTitle post =
    { post | title = String.toUpper (getTitle post) }