Tur*_*ion 4 haskell types pattern-matching pattern-guards
我尝试写一个变体show来处理字符串与其他实例不同Show,不包括"并直接返回字符串.但我不知道怎么做.模式匹配?警卫?我找不到任何关于在任何文件中.
这是我试过的,不编译的:
show_ :: Show a => a -> String
show_ (x :: String) = x
show_ x = show x
Run Code Online (Sandbox Code Playgroud)
如果可能的话,你应该将你的类型值包装String在newtype@wowofbob中.
然而,有时这是不可行的,在这种情况下,有两种通用方法可以使某些东西String具体识别.
第一种方法,即自然的Haskell方法,是使用类型类就像Show为不同类型获得不同的行为.所以你可以写
class Show_ a where
show_ :: a -> String
Run Code Online (Sandbox Code Playgroud)
然后
instance Show_ String where
show_ x = x
instance Show_ Int where
show_ x = show x
Run Code Online (Sandbox Code Playgroud)
等您要使用的任何其他类型.这样做的缺点是您需要为Show_所需的所有类型显式写出实例.
@AndrewC显示了如何将每个实例切割成一行,但您仍然必须明确地列出它们.理论上你可以解决这个问题,详见这个问题,但这并不令人愉快.
第二个选项是使用Typeable类获取真正的运行时类型信息,这在这种特定情况下非常简短:
import Data.Typeable
[...]
show_ :: (Typeable a, Show a) => a -> String
show_ x =
case cast x :: Maybe String of
Just s -> s
Nothing -> show x
Run Code Online (Sandbox Code Playgroud)
这不是一种自然的Haskell-ish方法,因为它意味着调用者无法详细说明该函数将从该类型中做什么.
类型类通常给出约束多态,因为特定函数的行为的唯一变化必须来自相关类型类实例中的变体.本Show_类给出了一些指示其主题,从它的名字,它可能会被记录在案.
然而,这Typeable是一个非常普遍的课程 您将所有内容委托给您正在调用的特定功能; 具有Typeable约束的函数可能对许多不同的具体类型具有完全不同的实现.
最后,对Typeable更接近原始代码的解决方案的进一步阐述是使用几个扩展:
{-# LANGUAGE ViewPatterns, ScopedTypeVariables #-}
import Data.Typeable
[...]
show_ :: (Typeable a, Show a) => a -> String
show_ (cast -> Just (s :: String)) = s
show_ x = show x
Run Code Online (Sandbox Code Playgroud)
使用ViewPatterns允许我们在cast内部编写一个模式,这可能更适合更复杂的例子.事实上,我们可以省略:: String类型约束,因为这种情况的主体强制s成为结果类型show_,即String无论如何.但这有点模糊,所以我认为最好是明确的.