关于singleton
库,我是一个新手,并且可能所遭受的损失超过了我在这里可以咀嚼的范围。
我已经成功地使用fromSing
将“单个类型”转换为“值级术语”(我的术语正确吗?)但是,我无法理解如何使用{{ 1}}和从概念上讲如何将在运行时的值转换为类型?
这是toSing
的文档所说的,我不太了解...
toSing
-- Convert an unrefined type to an existentially-quantified singleton type.
toSing :: Demote k -> SomeSing k
是这样的:
SomeSing
这是否意味着从概念上讲,-- An existentially-quantified singleton. This type is useful
-- when you want a singleton type, but there is no way of knowing,
-- at compile-time, what the type index will be. To make use of this
-- type, you will generally have to use a pattern-match:
foo :: Bool -> ...
foo b = case toSing b of
SomeSing sb -> {- fancy dependently-typed code with sb -}
基本上是在做以下事情:
fromSing
那是到目前为止,Haskell可以期望的最好结果吗?也就是说,我们需要对运行时值进行模式匹配,运行可以具有不同类型的函数,但最终它们应该统一为一个类型?
答案 0 :(得分:3)
如果您编译代码:
{-# OPTIONS_GHC -Wall #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TypeFamilies #-}
module SingletonExample where
import Data.Singletons.TH
singletons [d| data Value = Value1 | Value2 |]
带有标志-ddump-splices -dsuppress-uniques
,您可以看到singletons
库通过模板Haskell生成的实际代码。特别是,生成的SingKind
实例是:
instance SingKind Value where
type Demote Value = Value
fromSing SValue1 = Value1
fromSing SValue2 = Value2
toSing Value1 = SomeSing SValue1
toSing Value2 = SomeSing SValue2
因此,fromSing
和toSing
只是从(运行时)值到(运行时)单例再返回的样板转换函数。
也就是说,fromSing
和toSing
不在值和类型之间转换,它们在值和单例之间转换。当您编写的函数需要单例时,通常会使用toSing
:
g :: SValue value -> String
g SValue1 = "one"
g SValue2 = "two"
,但您拥有的只是一个关联值。在这种情况下,您可以使用有点尴尬的构造:
f :: Value -> String
f v = case toSing v of SomeSing sv -> g sv
以必要的单例呼叫g
。
事实证明,对于单例的通常使用情况,只有少数情况可以起作用和/或有帮助。结果,实际上很少见到toSing
用于单例代码。并且特别是,在处理与运行时相关的类型时,使用toSing
既没有必要,也常常没有特别有用。
最终,如果您想学习/理解singletons
库,则需要了解何时以及为什么单例有用(以及它们是类型的运行时表示形式的复杂而微妙的意义),而不是如何在它们及其关联值之间来回转换。为此,我建议阅读Hasochism论文Dependently Typed Programming with Singletons,搜索“ haskell中的依赖类型编程”和“ haskell单例”,并阅读您看到的每篇博客文章。 Weirich也有一些YouTube videos值得一试。