gpt4 book ai didi

haskell - Haskell 中的 C 风格枚举?

转载 作者:行者123 更新时间:2023-12-02 21:18:29 25 4
gpt4 key购买 nike

在 C 语言中,我们这样定义枚举:

enum E {
E0,
E1,
E2 = 3,
E3
};

注意E2 = 3表达式,枚举类型结果为 E0 == 0, E1 == 1, E2 == 3, E3 == 4 .

在 Haskell 中,我们无法在声明中指定枚举。实现不连续枚举的唯一方法是实现 Enum手动上课。

有什么方便的方法吗?

我写了一个demo使用 Template Haskell 生成 Enum实例。

data E = E0
| E1
| E2_3
| E3
deriving Show

enum ''E

我想知道是否有图书馆试图填补这个空白?

最佳答案

您可以使用 Template Haskell 的 reifyAnnotations 功能快速创建一些小而简单的东西。

首先,我们需要定义一个注释类型来保存枚举值:

{-# LANGUAGE DeriveDataTypeable #-}
module Def where

import Data.Data

data EnumValue = EnumValue Int deriving (Typeable, Data)

其次,我们需要一些 TH 代码来使用这些注释并将它们转换为 Enum 实例定义:

{-# LANGUAGE TemplateHaskell, QuasiQuotes #-}
module TH where

import Def
import Language.Haskell.TH.Syntax
import Language.Haskell.TH
import Control.Monad
import Data.List (mapAccumL)
import Data.Maybe

enumValues :: [(a, Maybe Int)] -> [(a, Int)]
enumValues = snd . mapAccumL (\next (x, mv) -> let v = fromMaybe next mv in (v+1, (x, v))) 0

enumFromAnns :: Name -> Q [Dec]
enumFromAnns name = do
TyConI (DataD _ _ _ cons _) <- reify name
eVals <- fmap enumValues $ forM cons $ \(NormalC conName []) -> do
anns <- reifyAnnotations (AnnLookupName conName)
let ev = case anns of
[EnumValue ev] -> Just ev
[] -> Nothing
return (conName, ev)
[d|
instance Enum $(conT name) where
fromEnum = $(lamCaseE [match (conP c []) (normalB $ lift v) [] | (c, v) <- eVals])
toEnum = $(lamCaseE [match (litP . IntegerL . fromIntegral $ v) (normalB $ conE c) [] | (c, v) <- eVals])|]

最后我们可以使用它(通过 small workaround to make sure the usage is in a new declaration group ):

{-# LANGUAGE TemplateHaskell #-}
module AnnotatedEnumExample where

import Def
import TH

data E = E1
| E2
| E42
| E43
deriving Show

{-# ANN E1 (EnumValue 1) #-}
{-# ANN E42 (EnumValue 42) #-}

-- Force new declaration group
return []

enumFromAnns ''E

使用示例:

*AnnotatedEnumExample> map fromEnum [E1, E2, E42, E43]
[1,2,42,43]
*AnnotatedEnumExample> map toEnum [1, 2, 42, 43] :: [E]
[E1,E2,E42,E43]

关于haskell - Haskell 中的 C 风格枚举?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33561183/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com