繁体   English   中英

有没有办法直接引用Haskell中的类型类实例?

[英]Is there a way to refer directly to typeclass instances in Haskell?

这样做的好处是可以在规范位置存储关于类型的某些元数据。 有时,在使用某些实例方法之前获取类型的值是不方便的; 例如,如果我有:

class Foo a where
  foo :: String
  foo = "Foo"

这实际上不是有效的Haskell。 相反,似乎我必须有类似的东西:

class Foo a where
  foo :: a -> String
  foo = const "Foo"

现在foo实际上会有类型Foo a => a -> String ,但我真的希望能够做类似于Instance Foo -> Stringfoo 为了在某​​些上下文中有用,可能还需要迭代所有(范围内?)实例,或者在其他上下文中,以便能够具体实现给定类型的实例。

我想问题是实例和类型类不是Haskell中的第一类实体?

“老派”这样做的方式是提供一个“虚拟”参数,其目的只是帮助编译器找到合适的实例。 在这个世界上,你的课程看起来像:

data Dummy a = Dummy

class Foo a where
    foo :: Dummy a -> String

-- usage:
boolFoo = foo (Dummy :: Dummy Bool)

事实上,这个技巧无处不在, Dummy类型被半标准化为Data.Proxy


但在现代GHC中有一种更好的方法: TypeApplications

启用此扩展后,您可以在调用类方法时直接指定类型:

class Foo a where
    foo :: String

boolFoo = foo @Bool

(这不仅适用于类方法;它适用于任何泛型函数,但要注意类型参数的顺序!)

您可能还需要启用AllowAmbiguousTypes才能声明此类。 虽然我不确定我是否正确记得这个,但我没有一台电脑方便检查。

旧的方式(我更喜欢)是使用代理

import Data.Proxy

class Foo a where
    foo :: Proxy a -> String

instance Foo FancyPants where
    foo _ = "a fancypants instance"

fooString :: String
fooString = foo (Proxy :: Proxy FancyPants)

所以我们实际上并不需要FancyPants类型的值来使用foo ,我们需要的只是Proxy FancyPants的值 - 但是你可以创建任何你想要的类型的代理。 这也可以在多态上下文中完成; 通常它需要使用ScopedTypeVariables扩展。

新的方法是使用TypeApplicationsAllowAmbiguousTypes扩展:

{-# LANGUAGE TypeApplications, AllowAmbiguousTypes #-}

class Foo a where
    foo :: String

instance Foo FancyPants where
    foo = "a fancypants instance"

fooString :: String
fooString = foo @FancyPants

这看起来更好,但在实践中使用它往往更加恼人,因为我无法完全按手指。

这回答了这个问题吗?

暂无
暂无

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

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