9

使用-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必须满足条件,但这对于某些类型(例如无序集合)根本无法保证,它不能保证元素的顺序保持不变。

这似乎非常不一致。

4

1 回答 1

5

两个扩展中重载的只是一个符号。这两种表示法的区别在于列表可以包含变量 ( [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

But fromList [x, y] is not a constructor pattern:对于给定的z,可能有几个不同 的值xy这样fromList [x, y] == z(在你的例子中,一个无序集合{1, 2}等于fromList [1, 2]但也等于fromList [2, 1]- 那么结果应该f {1, 2}True还是False

这表明,要使模式匹配起作用,Mylist a需要与同构[a]换句话说,toList需要满足适当规律的 a。然后我们可以通过应用于找到唯一的 这样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}使用 list notation表示您的无序集合[1, 2]。但是那样我们就会-XOverloadedLists--XOverloadedListPatterns可能不值得麻烦。

于 2021-03-25T21:29:13.313 回答