Haskell 如何打字

Haskell 如何打字,haskell,casting,Haskell,Casting,C#: Haskell? 在我看来,Haskell没有根类型的对象,这有点棘手 编辑:我不关心转换为字符串。我想知道如何进行类型转换(例如,查看对象是客户还是订单。在Haskell中,所有允许转换为字符串的类型都实例化了提供 static int F(object x) { return x is string ? 1 : 2; } 所以你的整个代码只是 show :: Show a => a -> String 或 对于相同的泛型类型f::Show a=>a->String(

C#:

Haskell? 在我看来,Haskell没有根类型的对象,这有点棘手


编辑:我不关心转换为字符串。我想知道如何进行类型转换(例如,查看对象是客户还是订单。

在Haskell中,所有允许转换为字符串的类型都实例化了提供

static int F(object x)
{
 return x is string ? 1 : 2;
}
所以你的整个代码只是

show :: Show a => a -> String

对于相同的泛型类型
f::Show a=>a->String
(对于所有可转换为字符串的类型
a
,获取此类型的值并返回字符串)

请注意,您不必像C#中那样进行显式的运行时类型检查,通用模板在编译时解析。您不需要多态根类型-像C#中那样的强制转换实际上有点复杂,并且违背了语言的概念。它不允许在类型之间进行任意强制转换,而是为某些类型定义了类型类n有意义的转换

请注意,兼容性是在编译时检查的:

f = show
在回答您编辑的问题时

正如我之前所说,Haskell中不允许任意转换(没有非常不安全的代码)。由于Haskell不是面向对象的,因此不存在需要任何强制转换的继承关系。根本不存在需要运行时检查/强制转换的毫无意义的
对象
值。要表达备选方案,您必须定义联合类型、类型类或使用
类型

在什么情况下,您遇到的对象是
客户
订单
?这种类型的值根本没有意义。请再次澄清

关于您的记录器示例: 您需要一个typeclass:

-- Working
f 1
f "Hallo"
f (1, 2)
f [1, 2, 3]

-- Not working
f (\x -> x + 1) 
在C#中,不做演员可能更有效:

class Loggable a where
    writeToLog :: a -> IO ()

在Haskell中有一个“show”类型类,任何实现该类型类的对象都可以调用show,因此不需要强制转换。

如果希望对象既可以是客户,也可以是订单,那么您应该引入一个新的数据类型“Customer | Order”,以便每个对象都带有一个类型标记,表明它是什么

我不知道Haskell的语法,但在F#中应该是

return x == null ? null : x.ToString();

更一般地说,在Haskell中,如果您想执行固定的OO类型层次结构之类的操作(对于一组固定的高度相关的类型,在某些情况下可以将它们视为相同的类型),您可以使用上述联合类型。另一方面,对于跨各种不相关类型的常见操作(如ToString/Show)您可以使用Haskell类型的类。

这是我以前尝试过的,我认为您做不到

哈斯克尔采取了非常不同的态度 方法。它从执行类型开始 使用类型检查器进行分析,以 在编译时理解你的程序 时间。严格检查类型 禁止类型转换,不允许 允许忽略类型错误。 因为类型是在编译时检查的 时间,没有逃避的余地 类型检查器,Haskell经常 描述为静态类型和 强类型


Dario是对的,通常在Haskell中,您希望创建一个类型类来分派某个对象的类型。也就是说,有一种类型安全的方法可以在Haskell中强制转换。这是通用编程库的一部分,允许您编写“有趣的”部分复杂嵌套数据类型的操作,而SYB填补了空白。大脑融合太棒了。以下是关于它的介绍

以下是演员阵容:

type CustOrOrd =
    | Cust of Customer
    | Ord of Order

let F (x:CustOrOrd) : int =
    match x with
    | Cust c -> 1
    | Ord o -> 2

let thing1 = Cust someCustomer
let thing2 = Ord someOrder
// can call F on thing1 or thing2

铸造和
/
实例
在该功能的语言中是有意义的。您的问题可以用几种方式回答:

  • Haskell没有子类型,因此
    /
    实例
    在Haskell中没有意义;只有显式转换。没有可扩展所有类型的
    对象
    类型
  • Haskell的类型类提供了特殊的多态性,并有助于为许多转换重载单个名称。例如(正如其他人所指出的)
    show
    是用于将任何类型转换为字符串的重载名称。类型类还可用于使某些转换(似乎)隐式
  • 泛型库的作者使用类型类创建了一个安全强制转换函数(其他人也指出了这一点)

正如Dario所观察到的,最直接的方法是使用它,它涵盖了所有标准类型,尽管您需要通过“
导出可键入的
”,或者为要涵盖的您自己的类型定义实现
typeOf
。这不是标准的Haskell 98,但它从6.2.2开始就在ghc中

您的代码可以实现:

cast :: (Typeable a, Typeable b) => a -> Maybe b
ghci> (cast 'a') :: Maybe Char
Just 'a'
ghci> (cast 'a') :: Maybe Bool
Nothing
ghci> (cast True) :: Maybe Bool
Just True
stringtyperep::TypeRep stringtyperep=somestring的类型 F::(可键入的'a)=>'a->整数 F x |(typeOf x==stringtyperep)=1 fx=2 一般来说,使用泛型编程可以更好地实现OO风格的类型反射,但这不是一个很好的例子

此外,typeclass
Typeable
中的所有类型都可以“强制”到中。

定义
Object
您自己 如果您的用例非常简单,那么最好自己定义对象类型,因此:

stringtyperep :: TypeRep stringtyperep = typeOf "somestring" F :: (Typeable 'a) =>'a -> Integer F x | (typeOf x == stringtyperep) = 1 F x = 2 显然,您必须为每个类型编写一个
实例
声明,您可能希望在使用
类型
的函数中用作对象。当您尝试为元组定义
实例
时,这可能会变得棘手,因为在Haskell中,如果两个元组的元素数不相同,那么它们的类型就不同因此,您可能必须编写无限多的
实例
声明,如下所示:

data Type = String | Integer | List | Bool
    deriving (Eq, Show)

class Object a where
    typeOf :: a -> Type

instance Object String  where typeOf _ = String
instance Object Integer where typeOf _ = Integer
instance Object [a]     where typeOf _ = List
instance Object Bool    where typeOf _ = Bool

f :: (Object a, Num b) => a -> b
f x = if typeOf x == String then 1 else 2
使用
Data.Typeable
如果您的使用变得更复杂,您可以尝试:


如果您愿意,您可以将
(undefined::String)
替换为
,以更容易理解的为准。

将任意类型强制转换为
data Type = String | Integer | List | Bool
    deriving (Eq, Show)

class Object a where
    typeOf :: a -> Type

instance Object String  where typeOf _ = String
instance Object Integer where typeOf _ = Integer
instance Object [a]     where typeOf _ = List
instance Object Bool    where typeOf _ = Bool

f :: (Object a, Num b) => a -> b
f x = if typeOf x == String then 1 else 2
data Type = String | Integer | List | Bool | Tuple
    deriving (Eq, Show)

instance Object ()              where typeOf _ = Tuple
instance Object (a)             where typeOf _ = Tuple
instance Object (a,b)           where typeOf _ = Tuple
instance Object (a,b,c)         where typeOf _ = Tuple
instance Object (a,b,c,d)       where typeOf _ = Tuple
instance Object (a,b,c,d,e)     where typeOf _ = Tuple
instance Object (a,b,c,d,e,f)   where typeOf _ = Tuple
instance Object (a,b,c,d,e,f,g) where typeOf _ = Tuple
import Data.Typeable

f :: (Typeable a, Num b) => a -> b
f x = if typeOf x == typeOf (undefined::String) then 1 else 2