我正在尝试遵循本教程:http://blog.jakubarnold.cz/2014/08/06/lens-tutorial-stab-traversal-part-2.html
我正在使用以下代码加载到ghci中:
{-# LANGUAGE RankNTypes, ScopedTypeVariables #-}
import Control.Applicative
import Data.Functor.Identity
import Data.Traversable
-- Define Lens type.
type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t
type Lens' s a = Lens s s a a
-- Lens view function. Omitting other functions for brevity.
view :: Lens s t a b -> s -> a
view ln x = getConst $ ln Const x
-- Tutorial sample data types
data User = User String [Post] deriving Show
data Post = Post String deriving Show
-- Tutorial sample data
john = User "John" $ map (Post) ["abc","def","xyz"]
albert = User "Albert" $ map (Post) ["ghi","jkl","mno"]
users = [john, albert]
-- A lens
posts :: Lens' User [Post]
posts fn (User n ps) = fmap (\newPosts -> User n newPosts) $ fn ps
从那里开始,像这样的简单东西起作用:
view posts john
但是,当我尝试进行下一步时,它不起作用:
view (traverse.posts) users
我得到:
Could not deduce (Applicative f) arising from a use of ‘traverse’
from the context (Functor f)
bound by a type expected by the context:
Functor f => ([Post] -> f [Post]) -> [User] -> f [User]
at <interactive>:58:1-27
Possible fix:
add (Applicative f) to the context of
a type expected by the context:
Functor f => ([Post] -> f [Post]) -> [User] -> f [User]
In the first argument of ‘(.)’, namely ‘traverse’
In the first argument of ‘view’, namely ‘(traverse . posts)’
In the expression: view (traverse . posts) users
我看到Lens的类型约束为Functor,而遍历对f的约束为Applicative。为什么这完全不起作用,为什么博客教程建议它起作用?
最佳答案
view
实际上具有比Lens s t a b -> s -> a
限制少的类型。
如果删除类型签名,ghci会告诉您view
的类型
:t view
view :: ((a1 -> Const a1 b1) -> t -> Const a b) -> t -> a
这种限制较少,因为必须在
Lens
函子中定义forall
函子,而只需要为Const a1
定义要查看的第一个参数。如果我们根据
Lens
中的名称重命名类型变量并限制a1 ~ a
,则此签名更有意义type Lens s t a b = forall f. Functor f =>
(a -> f b) -> s -> f t
view :: ((a -> Const a b) -> s -> Const a t) -> s -> a
view ln x = getConst $ ln Const x
关于haskell - 遍历的Haskell镜头教程,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27412517/