能否在SML中编写通用函数isList以判断参数是否为列表?
isList(x) function in SML that returns true iff x is a list? Great question! The short answer is: it depends on which SML implementation you're using and how strictly you want to adhere to standard SML'97 rules. Let's break down your options clearly:
1. Standard SML'97: Wrapper type + exception handling
Standard SML has a strict static type system, which means functions can't accept arbitrary untyped values directly. To work around this, we can create a universal wrapper type to hold any value, then use exception handling to test if it behaves like a list:
(* Define a wrapper type to encapsulate any value *) datatype 'a universal = Universal of 'a fun isList (Universal x) = let (* This helper only accepts lists; calling it on non-lists throws an exception *) fun check [] = true | check (_::_) = true in check x handle _ => false end
Usage examples:
isList (Universal 4);→ returnsfalseisList (Universal [1, 2, 3]);→ returnstrueisList (Universal ["apple", "banana"]);→ returnstrue
The tradeoff here is that you have to wrap every value in the Universal constructor. This is necessary because standard SML doesn't allow functions with the type 'a -> bool (a function that takes any type and returns a boolean) — such a type would bypass the language's static type safety guarantees.
2. PolyML: Runtime reflection (no wrapper needed)
If you're using PolyML (a popular SML implementation with extended runtime features), you can use its built-in reflection capabilities to directly check a value's type without any wrapping:
fun isList x = PolyML.TypeName.equal ( PolyML.Runtime.typeName x, PolyML.Runtime.typeName ([]: int list) -- Use any list to get the base list type name )
Usage examples (direct, no wrapping):
isList 4;→ returnsfalseisList [1, 2, 3];→ returnstrueisList #("hello", 42);→ returnsfalse
This works because all list types (regardless of their element type) share the same base type name in PolyML. Comparing the runtime type name of your input to any list's type name tells you if it's a list.
Why a "pure" universal isList isn't possible in standard SML
Standard SML's type system is designed to catch type errors at compile time, not runtime. A function that accepts any type and returns a boolean would bypass these checks, which goes against the language's core design principles. The wrapper approach is a way to opt into runtime type checking while still respecting the static type system.
内容的提问来源于stack exchange,提问作者align

