有人知道Haskell中是否有一个函数可以执行以下操作:
"Int" -> Int
"String" -> String
"Bool" -> Bool
即。它采用类型构造函数名称的字符串表示形式,并将其转换为实际类型构造函数,包括表达式和模式。
编辑: 我的总体目标是简化:
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”,然后将其转换回类型。
答案 0 :(得分:10)
通过简单地将Add
和Sub
个案件合并为一个案例,有一种更好的方法可以在没有任何模板Haskell或反射恶作剧的情况下重构您的代码:
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
上进行模式匹配。
答案 1 :(得分:2)
在哪种情况下?有模板Haskell和Data.Typeable
,但是对于一个实际有用的答案,您需要提供更多详细信息。
答案 2 :(得分:0)
嗯,这就是问题所在。
"String" -> String
这在Haskell-land中是胡言乱语,因为"String"
是一个值,但String
是一种类型。所以你可以试试这个:
String -> a
这不符合你的要求。您应该学习如何阅读类型签名,因为如果您无法读取类型签名,那么您将在Haskell中遇到严重障碍。上面的类型意味着“给我一个字符串,我可以给你一个你要求的任何类型的值。”此签名的前奏中有一个函数,它被称为error
,这不是你想要的。
听起来像你想要这些内容:
String -> TypeRep
抱歉,没有这样的功能。 TypeRep
不会实例化Read
类。
你实际试图在这做什么?如果你告诉我们你真正想做什么,我们可以帮助你解决这个问题,而不是试图帮助你有这个问题。
答案 3 :(得分: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
但从长远来看,这可能实际上并不是非常有用,具体取决于您拥有的案例数量。
通常,模式匹配是针对类型结构运行的,因此必须在编译类型中针对具体类型构造函数进行拼写。这是您拥有一个非常稳固的静态类型系统所需要付出的代价。