我不明白库中 first
的实现。
first
似乎是用 ***
递归定义的——我看不到递归何时结束!?
first :: a b c -> a (b,d) (c,d)
first = (*** id)
和
(***) :: a b c -> a b' c' -> a (b,b') (c,c')
f *** g = first f >>> arr swap >>> first g >>> arr swap
where swap ~(x,y) = (y,x)
第一个 f
是 (f *** id)
也就是 (第一个 f >>> arr swap >>> 第一个 id...)
和新的 first
将是另一个 (*** id)
等等...
最佳答案
如果你实现这样的箭头,你是对的:
instance Arrow MyType where
arr f = ...
然后尝试使用first
或(***)
,您将得到一个无限循环,因为这些实现非生产性地相互引用。但是,通过这种方式定义默认方法,您可以将 Arrow
实例化为
instance Arrow MyType where
arr f = ...
first t = ...
或
instance Arrow MyType where
arr f = ...
t *** t' = ...
以更方便/更高效的方式(取决于您关心的内容),缺少的方法将根据您指定的方法自动定义。
如果我们尝试实例化 Arrow
而不提供 first
或 (***)
的实现,我们将收到以下警告:
warning: [-Wmissing-methods]
• No explicit implementation for
either ‘first’ or ‘***’
• In the instance declaration for ‘Arrow MyType’
这是因为source配有 MINIMAL
pragma :
{-# MINIMAL arr, (first | (***)) #-}
它告诉编译器,即使提供了默认值,实例也不完整,除非它指定 arr
和 first
或 (*** )
。因此,需求被编码和检查。
至于您的评论:
Not necesseraly I can leave the default and then the recursion will take place by definition. specific implementation are not the question here...
如果没有实例,则无法使用类型类的方法。几乎不可能尝试,因为方法的类型总是引用类型,例如
class Arrow k where
first :: k a b -> k (a,c) (b,c)
...
当您使用first
时,您必须记住特定的k
才能使用结果,例如
print $ first (arr id) (1,2) -- using it at k ~ (->)
print =<< runKleisli (first (arr id)) (1,2) -- using it at Kleisli IO
在某些时候,程序的类型约束会将k
固定为具体的东西,这就是所使用的实例。没有实例就无法使用类。
(即使在事情排列方式无法确定特定实例的情况下,经典的例子是
show . read :: String -> String
编译器只会对你大喊大叫
• Ambiguous type variable ‘a0’ arising from a use of ‘read’
prevents the constraint ‘(Read a0)’ from being solved.
Probable fix: use a type annotation to specify what ‘a0’ should be.
如果程序无法编译,则不会无限递归!)
关于haskell - Arrow 库中 `first` 的实现,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57744404/