7

有谁知道 Haskell 中是否有这样的功能:

"Int" -> Int

"String" -> String

"Bool" -> Bool

IE。它采用类型构造函数名称的字符串表示,并将其转换为实际的类型构造函数,无论是在表达式中还是在模式中。

编辑:我的总体目标是简化以下内容:

transExp (Add exp1 exp2) vars
  = transExp exp1 vars ++ transExp exp2 vars ++ [IAdd]

transExp (Sub exp1 exp2) vars
  = transExp exp1 vars ++ transExp exp2 vars ++ [ISub]

变成单个模式匹配,所以基本上将 Add 或 Sub 转换为字符串,在前面添加“I”,然后将其转换回类型。

4

4 回答 4

10

有一种更好的方法可以在这里重构您的代码,而无需任何模板 Haskell 或反射恶作剧,只需将您的AddSub案例合并为一个:

data BinOp = Add | Sub | ...

data Expr = ...
          | BinOp BinOp Expr Expr
          | ...

transExp (BinOp op exp1 exp2) vars
    = transExp exp1 vars ++ transExp exp2 vars ++ [transOp op]
...

transOp Add = IAdd
transOp Sub = ISub

这样,我们使用数据类型直接表达二元运算符相关的事实,因此具有相似的翻译。BinOp Add exp1 exp2如果您想在某处添加特殊情况,您仍然可以进行模式匹配。

于 2011-11-17T11:36:34.697 回答
3

在什么情况下?有 Template Haskell 和Data.Typeable,但要获得真正有用​​的答案,您需要提供更多详细信息。

于 2011-11-17T10:14:17.253 回答
0

好吧,这就是问题所在。

"String" -> String

这在 Haskell-land 中是胡言乱语,因为"String"它是一个值,但String也是一个类型。所以你可以试试这个:

String -> a

这不符合您的要求。您应该学习如何阅读类型签名,因为如果您无法阅读类型签名,那么您将在 Haskell 中受到严重影响。上述类型的意思是,“给我一个字符串,我可以给你一个你要求的任何类型的值。” 前奏中有一个带有这个签名的函数,它被称为error,这不是你想要的。

听起来你想要一些类似的东西:

String -> TypeRep

抱歉,没有这个功能。 TypeRep不实例化Read类。

你到底在这里做什么? 如果您告诉我们您实际上想要做什么,我们可以帮助您解决这个问题,而不是试图帮助解决这个问题。

于 2011-11-17T10:42:47.290 回答
0

你不能这样做,因为字符串是运行时数据,类型必须在编译时完全解析。你可以用你的例子做的最好的事情是一个帮助函数来消除一些重复:

helper exp1 exp2 vars op = transExp exp1 vars ++ transExp exp2 vars ++ [op]
transExp (Add exp1 exp2) vars = helper exp1 exp2 vars IAdd
transExp (Sub exp1 exp2) vars = helper exp1 exp2 vars ISub

但从长远来看,这实际上可能不是很有用,具体取决于您拥有多少案例。

通常,模式匹配是针对类型结构运行的,因此必须在编译类型时针对具体类型构造函数进行说明。这是拥有真正可靠的静态类型系统所必须付出的代价。

于 2011-11-17T10:46:30.787 回答