简体   繁体   English

将字符串转换为Haskell中的Type构造函数

[英]Convert a String to a Type Constructor in Haskell

Does anyone know if there's a function in Haskell which does something like this: 有没有人知道Haskell中是否有一个函数可以做这样的事情:

"Int" -> Int

"String" -> String

"Bool" -> Bool

ie. 即。 it takes a string representation of a type constructor name, and converts it to the actual type constructor, both in an expression and in a pattern. 它采用类型构造函数名称的字符串表示形式,并将其转换为实际类型构造函数,包括表达式和模式。

edit: My overall goal is to simplify something like: 编辑:我的总体目标是简化:

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

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

Into a single pattern match, so basically convert Add or Sub to a string, add an "I" to the front, and convert it back to a type. 进入单个模式匹配,所以基本上将Add或Sub转换为字符串,在前面添加“I”,并将其转换回类型。

There is a much better way to refactor your code here without any Template Haskell or reflection shenanigans by simply joining your Add and Sub cases into one: 有一个更好的方法可以在没有任何模板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

This way, we're using the data type to express directly the fact that binary operators are related, and therefore have similar translations. 这样,我们使用数据类型直接表示二元运算符相关的事实,因此具有相似的翻译。 You can still pattern match on BinOp Add exp1 exp2 if you want to make a special case for addition somewhere. 如果你想在某个地方BinOp Add exp1 exp2特殊情况,你仍然可以在BinOp Add exp1 exp2模式匹配。

In which context? 在哪种情况下? There is Template Haskell and Data.Typeable , but for an actually helpful answer you need to provide more details. 有模板Haskell和Data.Typeable ,但是对于实际有用的答案,您需要提供更多详细信息。

Well, here's the problem. 好吧,这是问题所在。

"String" -> String

That's gibberish in Haskell-land, because "String" is a value but String is a type. 这在Haskell-land中是胡言乱语,因为"String"是一个值,但String是一种类型。 So you might try this: 所以你可以试试这个:

String -> a

This doesn't do what you want. 这不符合你的要求。 You should learn how to read type signatures, because if you can't read type signatures, you're going to be badly handicapped at Haskell. 您应该学习如何阅读类型签名,因为如果您无法读取类型签名,那么您将在Haskell中遇到严重障碍。 The above type means, "Give me a string and I can give you a value of any type you request." 上面的类型意味着“给我一个字符串,我可以给你一个你要求的任何类型的值。” There is a function in the prelude with this signature, it is called error , which is not what you want. 这个签名的前奏中有一个函数,它被称为error ,这不是你想要的。

It sounds like you want something along these lines: 听起来你想要这些东西:

String -> TypeRep

Sorry, no such function. 对不起,没有这样的功能。 TypeRep does not instantiate the Read class. TypeRep不实例化Read类。

What are you actually trying to do here? 什么是你真正想在这里做什么? If you tell us what you are actually trying to do, we can help you with that problem rather than try to help with this problem. 如果您告诉我们您实际上想要做什么,我们可以帮助您解决这个问题,而不是尝试帮助解决这个问题。

You can't do it, because strings are runtime data and types have to be entirely resolved at compile time. 你不能这样做,因为字符串是运行时数据,类型必须在编译时完全解析。 The best you can probably do with your example is a helper function to eliminate some of the duplication: 你可以用你的例子做的最好的是帮助函数,以消除一些重复:

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

But this may not actually be very useful in the long term, depending on how many cases you have. 但从长远来看,这可能实际上并不是非常有用,具体取决于您拥有的案例数量。

In general, pattern matching is something that runs against type structures, so it has to be spelled out at compile type against concrete type constructors. 通常,模式匹配是针对类型结构运行的,因此必须在编译类型中针对具体类型构造函数进行拼写。 This is the price you have to pay for having a really solid static type system. 这是您拥有一个非常稳固的静态类型系统所需要付出的代价。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM