2017-10-20 116 views
0

我想编写一个样本函数,该函数接受任何类型的列表,并且仅当列表是一个实数列表时才返回头元素。ML如何检查列表类型并给出错误按摩?

否则,函数应该给出错误信息

。 。 。 E r r o r:操作符和操作数不是。 。 。

datatype typeR = Real of real 
fun head(xs) = 
    case xs of 
     [] => raise List.Empty | 
      Real (x::_) => x:real ; 

回答

1
(fn x:real list => hd x) [ 4 ,5 ]; 
out> error: Type error in function application 
(fn x:real list => hd x) [ 4.0 ,5.0 ]; 
out> it = 4.0: real 
+4

请添加您的代码的说明。 –

+0

'(fn x:real list => hd x)'不包含任何类型的列表*,但仅包含实数列表。但是,只有当列表是一个reals *列表时,它才会返回head元素,并且在不受reals列表影响时会产生类型错误。或者,'hd:real list - > real'。 –

2

这不是完全清楚你在做什么之后 - 你不能写一个函数,采用“任何类型”,然后检查参数类型。
(编写head(xs),没有类型注释,不会使head可以接收任意类型的函数,它的类型推断。)

如果你想有一个功能typeR list -> real,您的主要错误是写Real (x::_),你应该写(Real x) :: _
即,

fun head(xs) = 
    case xs of 
     [] => raise List.Empty 
    | (Real x)::_ => x 

,或者更惯用,

fun head [] = raise List.Empty 
    | head (Real x :: _) = x 
0

首先一些反馈:

  • 此功能是容易失败,因为它仅接受其可能的余量输入。尽可能写出全部功能。

  • raise Empty不会描述列表非空的情况,但第一个元素不包含实数。那么应该提出另一个例外。

  • 以下需求是高度可疑的。

    否则,函数应该给错误消息

    。 。 。 E r r o r:操作符和操作数不是。 。 。

    它表明您不区分运行时异常和编译时错误。这对于使用动态类型语言的编程经验是有症状的,其中错误和异常都是在程序启动后处理的。

然后一些想法:

解释在标准ML是同质的,这意味着它们可以仅是一种类型的在编译的类型检查阶段确定的时间。有几种方法可以解决这个问题并实现更多的动态输入;

  • Using algebraic data types [wiki.haskell。组织]:

    datatype dynamic = R of real 
           | I of int 
           | B of bool 
           | S of string 
    fun headR [] = raise Empty 
        | headR (R r :: _) = r 
        | headR _ = raise Domain 
    

    然后headR实际上并没有接受任何类型。它只接受一个dynamic,它可以容纳任意固定数量的具有任意类型参数的值构造函数。这个模拟异构列表:

    val foos = [R 42.0, I 10, B true, S "Hello, World!"] 
    
  • Using exceptions [informallyabstract.blogspot.com]:

    datatype dynamic = Dynamic of exn 
    exception IsReal of real 
    fun wrap_real r = Dynamic (IsReal r) 
    fun unwrap_real (Dynamic ex) = raise ex handle IsReal r => r 
    fun headR (d::_) = unwrap_real 
        | headR [] = raise Empty 
    

    headR然后同样仅接受一个类型,dynamic,并且未能与该期间使用的任何异常,而不是的real包装。使用异常和常规datatype定义之间的区别是异常可以在以后的新构造扩展:

    exception IsString of string 
    fun wrap_string r = Dynamic (IsString r) 
    fun unwrap_string (Dynamic ex) = raise ex handle IsString r => r 
    val foos = [wrap_real 42.0, wrap_string "This didn't exist before."] 
    

也不是可取的,因为它们引入了运行时故障的不必要的风险。