请求提供OpenSum类型weaken函数的使用示例以完成《Thinking With Types》练习11.2-i
请求提供OpenSum类型weaken函数的使用示例以完成《Thinking With Types》练习11.2-i
嘿,我完全懂你现在的困惑——光看类型签名和那段简短的描述,确实很难一下子get到weaken函数到底在干啥。不如我给你几个具体的使用例子,结合代码帮你理清楚它的作用!
首先先快速回顾下OpenSum的本质:它是一个可扩展的和类型(相当于动态版的Either家族),OpenSum f ts意味着这个值是f t类型的,其中t是类型列表ts里的某一个成员。
那咱们先搞点简单的测试类型和OpenSum实例:
import Data.Functor.Identity -- 定义几个测试用的简单类型 data Foo = Foo Int deriving Show data Bar = Bar String deriving Show data Baz = Baz Bool deriving Show -- 创建两个属于OpenSum Identity '[Foo, Bar]的实例 fooSum :: OpenSum Identity '[Foo, Bar] fooSum = UnsafeOpenSum 0 (Identity (Foo 42)) -- 对应列表里的第一个类型Foo barSum :: OpenSum Identity '[Foo, Bar] barSum = UnsafeOpenSum 1 (Identity (Bar "hello")) -- 对应列表里的第二个类型Bar
现在,weaken函数的作用就是把这个开放和类型的“可能性集合”拓宽——具体来说,就是在原来的类型列表ts前面加一个新类型x,生成新的类型x ': ts,同时把原来的OpenSum值适配到这个新的类型上。
比如我们想把上面的fooSum和barSum拓宽到包含Baz的类型列表里,就可以这么用:
-- 把fooSum弱化,现在它属于更大的类型集合 '[Baz, Foo, Bar]' weakenedFoo :: OpenSum Identity '[Baz, Foo, Bar] weakenedFoo = weaken fooSum -- 同理处理barSum weakenedBar :: OpenSum Identity '[Baz, Foo, Bar] weakenedBar = weaken barSum
这里的关键是:原来的fooSum原本只能表示Identity Foo或Identity Bar,经过weaken之后,它的类型变成了包含Identity Baz的更大集合,但原来的值本身并没有改变——只是它在新的类型列表里的索引位置往后移了一位(原来的索引0变成了1,索引1变成了2,因为新类型Baz占了第一个位置)。
再给你换个f的例子,比如用Maybe:
-- 一个包含Maybe Int的OpenSum maybeIntSum :: OpenSum Maybe '[Int, String] maybeIntSum = UnsafeOpenSum 0 (Just 123) -- 弱化后,类型变成了包含Maybe Bool的更大集合 weakenedMaybeInt :: OpenSum Maybe '[Bool, Int, String] weakenedMaybeInt = weaken maybeIntSum
理解了这些例子之后,你应该能明白:weaken就是给开放和类型“扩容”——在可选类型的最前面加一个新选项,同时让原来的有效值在新的扩容后的类型里依然合法。
备注:内容来源于stack exchange,提问作者Michael Litchard
相关产品推荐
相关产品推荐

