Haskell 我可以在类型名称上进行模式匹配吗?

Haskell 我可以在类型名称上进行模式匹配吗?,haskell,Haskell,是否可以在类型名本身而不是在类型的某个构造函数上进行模式匹配 下面是一个精心设计的示例,其中包含未编译的代码,我希望能够解释我的目的: what::a->String what(x::String)=“这是一个字符串!” 什么(x::Int)=“这是一个Int!” what x=“不确定是什么。” 在某种程度上,您试图在Haskell中重载函数。看看这篇文章,它解释了一个涉及类型类的方法,它可以做到这一点:在某种程度上,你试图在Haskell中重载一个函数。看看这篇文章,它解释了一个涉及类型类的

是否可以在类型名本身而不是在类型的某个构造函数上进行模式匹配

下面是一个精心设计的示例,其中包含未编译的代码,我希望能够解释我的目的:

what::a->String
what(x::String)=“这是一个字符串!”
什么(x::Int)=“这是一个Int!”
what x=“不确定是什么。”

在某种程度上,您试图在Haskell中重载函数。看看这篇文章,它解释了一个涉及类型类的方法,它可以做到这一点:

在某种程度上,你试图在Haskell中重载一个函数。看看这篇文章,它解释了一个涉及类型类的方法,它可以做到这一点:

不,这是不可能的


根据类型执行不同操作的唯一方法是使用针对每种类型实现不同的typeclass方法。

不,这是不可能的


根据类型执行不同操作的唯一方法是使用针对每种类型实现的不同类型类方法。

以下是使用类型类的版本:

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances  #-}
module Test where

class What a where
  what :: a -> String

instance What String where
  what _ = "It's a String!"

instance What Int where
  what _ = "It's an Int"
例如:

λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what True
"not sure"
如果您想要else案例:

例如:

λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what True
"not sure"

以下是使用类型类的版本:

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances  #-}
module Test where

class What a where
  what :: a -> String

instance What String where
  what _ = "It's a String!"

instance What Int where
  what _ = "It's an Int"
例如:

λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what True
"not sure"
如果您想要else案例:

例如:

λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what "hi"
"It's a String!"
λ> what (1 :: Int)
"It's an Int"
λ> what True
"not sure"
警告 请注意,您要求的是一些非常不地道的东西。不管你实际上想做什么,这可能不是正确的方法

解决方案 你的顶级类型签名表明你可以处理任何类型的东西,但这是不可能的。类型在编译时都会丢失,因此您需要一些东西来通知代码类型是什么,以及一些东西来做出分支决策

这里有一些使用较少的类,您可以依靠它们。其中一个称为
Typeable
,这是一个用于具有运行时表示的类型的类:

class Typeable (a :: k) where
  Data.Typeable.Internal.typeRep# :: GHC.Prim.Proxy# a -> TypeRep
为了在您的案例中使用typeable,您将约束添加到类型变量中,并使用
typeOf
获取类型表示:

{-# LANGUAGE MultiWayIf #-}
import Data.Typeable

what :: Typeable a => a -> String
what x =
    let ty = typeOf x
    in if | ty == intTy -> "It's an Int!"
          | ty == strTy -> "It's a String!"
          | otherwise -> "Something else, namely: " ++ show ty
  where
  strTy = typeOf ""
  intTy = typeOf (0 :: Int)
屈服操作:

*Main> what (1::Int)
"It's an Int!"
*Main> what "foo"
"It's a String!"
*Main> what 1.1
"Something else, namely: Double"
警告 请注意,您要求的是一些非常不地道的东西。不管你实际上想做什么,这可能不是正确的方法

解决方案 你的顶级类型签名表明你可以处理任何类型的东西,但这是不可能的。类型在编译时都会丢失,因此您需要一些东西来通知代码类型是什么,以及一些东西来做出分支决策

这里有一些使用较少的类,您可以依靠它们。其中一个称为
Typeable
,这是一个用于具有运行时表示的类型的类:

class Typeable (a :: k) where
  Data.Typeable.Internal.typeRep# :: GHC.Prim.Proxy# a -> TypeRep
为了在您的案例中使用typeable,您将约束添加到类型变量中,并使用
typeOf
获取类型表示:

{-# LANGUAGE MultiWayIf #-}
import Data.Typeable

what :: Typeable a => a -> String
what x =
    let ty = typeOf x
    in if | ty == intTy -> "It's an Int!"
          | ty == strTy -> "It's a String!"
          | otherwise -> "Something else, namely: " ++ show ty
  where
  strTy = typeOf ""
  intTy = typeOf (0 :: Int)
屈服操作:

*Main> what (1::Int)
"It's an Int!"
*Main> what "foo"
"It's a String!"
*Main> what 1.1
"Something else, namely: Double"

是的,我不想做这么不地道的事。我只是想知道我是否遗漏了一些语法。感谢您提供有关
数据的信息。尽管可以键入
!是的,我不想做这么不地道的事。我只是想知道我是否遗漏了一些语法。感谢您提供有关
数据的信息。尽管可以键入
!请注意,Haskell通常是静态类型的,因此编译器需要提前知道类型。但是,您可以使用类型类重载函数。请注意,Haskell通常是静态类型的,因此编译器需要提前知道类型。但是,您可以使用typeclasses重载函数。我知道为什么需要
TypeSynonymInstances
String~[Char]
)以及为什么需要
OverlappingInstances
在最后一个(
What a
Int
String
重叠)但是为什么你需要
FlexibleInstances
扩展呢?你也需要
字符串的扩展(我的GHC说)啊,我想因为你可以为
[Int]
定义一个,为
[Char]
@epsilonhalbe定义一个,如果我掌握了技术细节,那是因为
[Char]~[]Char
是不允许的,因为它必须是
[]a
而没有
FlexibleInstances
(“所有实例类型必须是(T a1…an)形式,其中a1…an是不同的类型变量”)我明白了为什么需要
类型同义词实例
字符串~[Char]
)为什么在最后一个中需要
OverlappingInstances
什么是
Int
String
的重叠)但是为什么需要
FlexibleInstances
扩展呢?你也需要
String
的扩展(我的GHC说)啊,我想因为你可以为
定义一个[Int]
和一个用于
[Char]
@epsilonhalbe如果我正确理解了技术细节,那是因为
[Char]~[]Char
是不允许的,因为它必须是
[]a
而没有
FlexibleInstances
(“所有实例类型都必须是形式(T a1…an),其中a1…an是不同的类型变量”)