是“表达问题"吗?可在F#中解决吗? [英] Is the "expression problem" solvable in F#?

查看:71
本文介绍了是“表达问题"吗?可在F#中解决吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我一直在看一个有趣的视频,其中Haskell中的类型类用于解决所谓的表达式问题".大约15分钟后,它显示了如何使用类型类基于区分的并集进行扩展以打开"数据类型-可以单独添加其他区分符,而无需修改/重建原始定义.

I've been watching an interesting video in which type classes in Haskell are used to solve the so-called "expression problem". About 15 minutes in, it shows how type classes can be used to "open up" a datatype based on a discriminated union for extension -- additional discriminators can be added separately without modifying / rebuilding the original definition.

我知道F#中没有类型类,但是有没有办法使用其他语言功能来实现这种可扩展性呢?如果没有,那么我们可以在多大程度上解决F#中的表达问题?

I know type classes aren't available in F#, but is there a way using other language features to achieve this kind of extensibility? If not, how close can we come to solving the expression problem in F#?

澄清:我假设问题的定义如

Clarification: I'm assuming the problem is defined as described in the previous video in the series -- extensibility of the datatype and operations on the datatype with the features of code-level modularization and separate compilation (extensions can be deployed as separate modules without needing to modify or recompile the original code) as well as static type safety.

推荐答案

正如约尔格(Jörg)在评论中指出的那样,这取决于您对 solve 的理解.如果您的意思是 solve 包括某种类型的类型检查,以确保在某些情况下您不丢失某些函数的实现,则F#不会给您任何优雅的方式(我不确定Haskell解决方案是否出色).您可以使用kvb提到的SML解决方案或

As Jörg pointed out in a comment, it depends on what you mean by solve. If you mean solve including some form of type-checking that the you're not missing an implementation of some function for some case, then F# doesn't give you any elegant way (and I'm not sure if the Haskell solution is elegant). You may be able to encode it using the SML solution mentioned by kvb or maybe using one of the OO based solutions.

实际上,如果我正在开发一个需要解决该问题的真实系统,那么我会选择一种解决方案,该解决方案不会对您进行全面检查,但是使用起来容易得多.

In reality, if I was developing a real-world system that needs to solve the problem, I would choose a solution that doesn't give you full checking, but is much easier to use.

一个草图是使用 obj 作为类型的表示,并使用反射来定位为个别情况提供实现的函数.我可能会使用某些属性标记所有零件,以使检查更加容易.将应用程序添加到表达式的模块可能如下所示:

A sketch would be to use obj as the representation of a type and use reflection to locate functions that provide implementation for individual cases. I would probably mark all parts using some attribute to make checking easier. A module adding application to an expression might look like this:

[<Extends("Expr")>]  // Specifies that this type should be treated as a case of 'Expr'
type App = App of obj * obj

module AppModule = 
  [<Implements("format")>] // Specifies that this extends function 'format'
  let format (App(e1, e2)) =
    // We don't make recursive calls directly, but instead use `invoke` function
    // and some representation of the function named `formatFunc`. Alternatively
    // you could support 'e1?format' using dynamic invoke.
    sprintfn "(%s %s)" (invoke formatFunc e1) (invoke formatFunc e2)

这不会为您提供任何类型检查,但是它为您提供了一个相当优雅的解决方案,该解决方案易于使用,并且实现起来并不困难(使用反射).在编译时不会检查您是否缺少大小写,但是您可以轻松地为此编写单元测试.

This does not give you any type-checking, but it gives you a fairly elegant solution that is easy to use and not that difficult to implement (using reflection). Checking that you're not missing a case is not done at compile-time, but you can easily write unit tests for that.

这篇关于是“表达问题"吗?可在F#中解决吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆