为什么IsList需要toList?

使用时-XOverloadedStrings你可以实现IsString只需要一个函数fromString。现在,如果您想使用字符串文字进行模式匹配,您还必须实现Eq,这是有道理的:

f :: MyString -> Bool
f "foo" = True
f _ = False

-- equivalent to
f x
  | x == fromString "foo" = True
  | otherwise             = False

但是,为什么使用的IsList类型类-XOverloadedLists需要您实现toList?在wiki 中,唯一提到的用例toList是模式匹配。我知道这Eq对于列表模式匹配是不够的。但后来toList应该是在唯一需要不同类型的类,如果你想使用列表模式匹配与你的类型,就像IsString没有要求 Eq

对我来说,令人讨厌的事情是fromList . toList = id必须满足条件,但是对于某些类型(例如无序集合,它不能保证元素的顺序保持不变),这根本无法保证。

这似乎非常不一致。

回答

两个扩展中的重载只是一个符号。两种表示法之间的区别在于,列表可以包含变量 ( [x, y]) 而字符串不能:Haskell 不会像这样进行变量插值let x = "apple" in "I like {x} pie")

当我在模式中使用任一符号时,这种差异变得很重要:我希望能够在模式中绑定变量,例如

f :: MyList Int -> Bool
f [x, y] = x > y

...虽然我可以使用字符串文字作为模式

 f :: MyString -> Bool
 f "apple" = True 

...那些永远不会绑定变量

要查看这产生的差异,假设-XOverloadedLists将完全像-XOverloadedStrings. 模式匹配

f [x,y] = x > y

将被翻译为

f z
 | z == fromList [x, y] = x > y

fromList [x, y] 不是构造函数模式:对于给定的z,可能有几个不同的 值,x并且y这样fromList [x, y] == z(在您的示例中,无序集合{1, 2}等于fromList [1, 2]但也为fromList [2, 1]- 那么结果应该f {1, 2}True还是False

这表明要使模式匹配起作用,Mylist a需要同构[a],换句话说,toList需要满足适当的定律。然后我们可以找到唯一的 x, y使得z == fromList [x, y]通过应用toListz,所以翻译是

f z
 | toList z == [x, y] = x > y

或者,使用视图模式(甚至Eq不再需要):

f (toList -> [x,y]) = x > y

因此,最终,IsList没有 的类toList将不允许重载列表模式,但仍然可以{1, 2}使用列表符号表示无序集合[1, 2]。但是,我们必须-XOverloadedLists-XOverloadedListPatterns-可能不值得冒这个险。


以上是为什么IsList需要toList?的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>