我以为我很好地理解了惰性,直到我想出了下面的代码,它产生了一个<<loop>>错误。
weird = ([1],[2]) <> weird
main = print (head $ fst weird)
Run Code Online (Sandbox Code Playgroud)
直观上,我认为 Haskell 会这样做:“我需要 的第一个元素weird。而且我需要第一个元素的头。所以我需要计算。现在我从对的半群实例中fst weird知道(或者我是吗??) fst weird = [1] ++ fst weird. 太好了,我该回来了1”
我哪里弄错了?
在 Haskell 中,类Bifunctor定义如下:
class Bifunctor p where\n bimap :: (a -> b) -> (c -> d) -> p a c -> p b d\nRun Code Online (Sandbox Code Playgroud)\n在范畴论中,根据ncatlab,双函子“只是一个域为产品类别的函子:对于 C1、C2 和 D 类别,函子 F:C1\xc3\x97C2\xe2\x9f\xb6D 称为双函子从C1和C2到D。”
\n现在,如果我必须实现分类定义,我会编写以下内容:
\nclass MyBifunctor p where\n myBimap :: ((a,c) -> (b,d)) -> p a c -> p b d\nRun Code Online (Sandbox Code Playgroud)\n特别是,myBimap看起来很像fmap,我想这就是我们想要的,因为双函子也是函子。
现在为了进一步推动这一点,因为base 4.18.0,添加了量化约束:
class (forall a. Functor (p a)) => Bifunctor p …Run Code Online (Sandbox Code Playgroud) Monoid如果我编写一个操作极其复杂的实例(<>),GHC 会知道吗?
mempty <> x = x
x <> mempty = x
Run Code Online (Sandbox Code Playgroud)
并避免计算(<>)?
我还对您如何获得该信息感兴趣,以及如果此优化不存在,这是否可以完成或之前已讨论过。