如何在Haskell中建模此可检索结构?

问题描述 投票:0回答:1

我正在尝试通过Haskell类型系统为kdb / q“原子和列表”建模。

在kdb / q中,所有数据都是从原子构建的。原子是特定数据类型的不可约值。 Int,布尔值和char是原子的示例。列表是从原子构建的有序集合。由于q是向量语言,因此大多数内置操作都是原子的,因此它递归到参数结构中,直到到达原子为止。

例如:(1; 2; 3)是整数1,2,3的简单列表(1.0; 2;(3; 4; 5))是1.0(float),2(int)和简单的int列表(3; 4; 5)的常规列表]

neg是一个否定一个数字的函数。例如:neg 1产生-1而neg -1.0产生1f

并且取负(1.0; 2;(3; 4; 5))得出(-1f; -2;(-3; -4; -5))。

这就是促使我尝试在Haskell类型中对此行为进行建模的原因。数据类型应包含原子类型和列表。

以下是我到目前为止的简化版本。而且我还进一步尝试使其成为可折叠和可遍历的实例。

data Atom = I Int
          | C Char
          | D Double 
          deriving Show

data Q a = QAtom a 
         | QList [Q a]
         deriving Show

instance Functor Q where
    fmap f (QAtom a) = QAtom (f a)
    fmap f (QList qs) = QList $ fmap (fmap f) qs

instance Foldable Q where
    foldMap f (QAtom a) = f a
    foldMap f (QList qs) = mconcat $ fmap (foldMap f) qs

instance Traversable Q where
    sequenceA (QAtom fa) = fmap QAtom fa
    sequenceA (QList []) = pure $ QList []
    sequenceA (QList (qfa:qfas)) = concatL <$> (sequenceA qfa) <*> (sequenceA (QList qfas))
        where
            concatL (QAtom a) (QList qas) = QList ((QAtom a):qas)

这就是我所拥有的,并且可以编译,但是我并不特别喜欢concatL函数,该函数不能根据类型覆盖所有模式。一旦我开始向Q添加新的值构造函数QDict [(Q Atom,Q a)],情况就会变得更糟。

我是否正确建模了原始数据?我是否应该尝试使其可穿越?但是,我认为,如果需要将数据类型与Maybe或Either结合使用以对错误进行建模,则Traversable是必需的。

任何建议都值得赞赏。

我正在尝试通过Haskell类型系统为kdb / q“原子和列表”建模。在kdb / q中,所有数据都是从原子构建的。原子是特定数据类型的不可约值。 Int,boolean和char ...

haskell kdb algebraic-data-types traversable
1个回答
1
投票

任何类型最多具有一个Traversable实例,并且编译器知道如何为您派生它。如果先执行:set -ddump-deriv -dsuppress-all -XDeriveTraversable -XStandaloneDeriving,然后执行deriving instance Traversable Q,则可以看到“正确”的答案。如果您掌握了这些知识并将其应用于您的实例,您将获得以下信息:

© www.soinside.com 2019 - 2024. All rights reserved.