当前位置:  开发笔记 > 编程语言 > 正文

基本类型的模式匹配

如何解决《基本类型的模式匹配》经验,为你挑选了1个好方法。

这是我想要的:

f n = case n of
  String -> "string"
  _ -> "other"

或者其他的东西。f如果要用字符串调用,我想映射到文字“字符串”,否则要映射为“其他”。这不能像我正在做的那么难。



1> leftaroundab..:

If you're coming from JS and Python it's understandable you think that something that this should be possible – after all, in those languages a type is essentially a particular property of a value. But that's not at all how the Haskell type system works! In fact, types and values belong to completely separate “universes”: types only exist at compile time, values only at runtime. It's still true that every value belongs to a type, but this information is already completely resolved at compile-time. At runtime it is generally not necessary to dispatch on types, because the compiler has already done that earlier, and it can never be possible that a value of type other than the valid one is ever passed in. So this would always be redundant. In fact the type information is removed before the program is run.
So in the direct sense, what you're trying to accomplish is indeed impossible. Or, cynically speaking, it's trivial:

f :: String -> String
f _ = "string"

Generally, if you find yourself wanting to runtime-dispatch on types it's a sign that you should probably have started out with a variant type in the first place:

data StringOrInt = It'sAString String | It'sAnInt Int

f :: StringOrInt -> String
f (It'sAString _) = "string"
f (It'sAnInt _) = "int"

...ideally with more descriptive, application-specific names.

That said, it is actually possible to have “dynamically typed” values in Haskell, like in Python. You just need to request the wrapper that contains the type information which the compiler would otherwise erase before the runtime:

{-# LANGUAGE TypeFamilies #-}

import Data.Dynamic
import Type.Reflection

f :: Dynamic -> String
f (Dynamic t _)
   = case eqTypeRep t (typeOf "string") of
       Just HRefl -> "string"
       _          -> "other"

Example usage:

main = do
   putStrLn . f $ toDyn "bla"
   putStrLn . f $ toDyn True
   putStrLn . f $ toDyn 'y'

yielding

string
other
other

f比笨拙的eqTypeRep构造更优雅的书写方式是

f :: Dynamic -> String
f s = case fromDynamic s :: Maybe String of
       Just _ -> "string"
       _      -> "other"

推荐阅读
爱唱歌的郭少文_
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有