Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 是不是不可能让复合透镜绑定?_Haskell_Functor_Haskell Lens_Unification - Fatal编程技术网

Haskell 是不是不可能让复合透镜绑定?

Haskell 是不是不可能让复合透镜绑定?,haskell,functor,haskell-lens,unification,Haskell,Functor,Haskell Lens,Unification,我很难理解通过帮助类型检查器,下面的内容是可行的,还是完全不可能的。 设置有点随意,我只需要一些带有镜头的嵌套数据类型,这里称为A,B,C 我的问题是,如果我立即使用它调用类似于view的东西,我可以使用复合镜头(bLens.a),但是如果我尝试让bind并给它命名,我会收到错误消息 {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE MonoLocalBinds #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE

我很难理解通过帮助类型检查器,下面的内容是可行的,还是完全不可能的。 设置有点随意,我只需要一些带有镜头的嵌套数据类型,这里称为
A
B
C

我的问题是,如果我立即使用它调用类似于
view
的东西,我可以使用复合镜头
(bLens.a)
,但是如果我尝试让bind并给它命名,我会收到错误消息

{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MonoLocalBinds #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}

module Debug where

import Control.Eff
import Control.Eff.Reader.Strict
import Control.Lens

data A = A

data B = B
  { _a :: A
  }
makeLenses ''B

data C = C
  { _b :: B
  }
makeLenses ''C

askLensed :: ( Member (Reader r) e ) => Lens' r a -> Eff e a
askLensed l = view l <$> ask

works :: ( Member (Reader C) e ) => Lens' C B -> Eff e A
works bLens = do
  askLensed (bLens . a)

doesNotWork :: ( Member (Reader C) e ) => Lens' C B -> Eff e A
doesNotWork bLens = do
  let compositeLens = bLens . a
  askLensed compositeLens

doesNotWork2 :: ( Member (Reader C) e ) => Lens' C B -> Eff e A
doesNotWork2 bLens = do
  let compositeLens :: Lens' C A = bLens . a
  askLensed compositeLens

butThisIsFine :: Lens' C B -> Lens' C A
butThisIsFine bLens =
  let compositeLens = bLens . a in compositeLens
以及:


我尝试添加类型签名,明确量化了
f
函子
约束,但迄今为止没有成功。

简化许多事情的经验法则是不要使用
镜头(或
镜头
,或
Setter
等)作为函数参数,除非您确实需要它,否则使用optic多态性,而是使用
ALens
(或
ALens'
ASetter
)版本,这样可以避免秩2多态性问题

问题是,如果在
do
块中给
compositeLens
一个名称,那么它必须有一个不能再从上下文推断的类型。但是,
Lens'ca
是一个隐藏的多态类型,这使得类型推断相当复杂。如果您给出一个明确的签名,实际上是可以的:

doesActuallyWork2 :: ( Member (Reader C) e ) => Lens' C B -> Eff e A
doesActuallyWork2 bLens = do
  let compositeLens :: Lens' C A
      compositeLens = bLens . a
  askLensed compositeLens
您的版本
doesNotWork2
不起作用,因为带有内嵌签名的定义被翻转到RHS,如

doesNotWork2 :: ( Member (Reader C) e ) => Lens' C B -> Eff e A
doesNotWork2 bLens = do
  let compositeLens = bLens . a :: Lens' C A
  askLensed compositeLens
…其中,
compositeLens
再次尝试将刚刚给定的类型专门化为一个特定的函子,这是无法完成的

更直接的解决方案是完全避免这种局部多态性,而您实际上并不需要这种多态性:如果将
ALens'
作为参数,则局部绑定会自动采用单态类型:like

worksEasily :: ( Member (Reader C) e ) => ALens' C B -> Eff e A
worksEasily bLens = do
  let compositeLens = bLens . a
  askLensed compositeLens
其实不完全是这样,;事实证明,您不想在这里使用
ALens
,而是
获取
。找到这个问题的最简单方法是删除askLensed的签名,让编译器告诉你它推断出了什么,然后从中向后操作

askLensed :: ( Member (Reader r) e ) => Getting a r a -> Eff e a
askLensed l = view l <$> ask

worksEasily :: ( Member (Reader r) e ) => Getting A r B -> Eff e A
worksEasily bLens = do
  let compositeLens = bLens . a
  askLensed compositeLens
askLensed::(成员(读者r)e)=>获取r a->Eff e a
askLensed l=视图l询问
轻松工作::(成员(读者r)e)=>获得r B->Eff e A
工作地点:bLens=do
让复合元素=混合元素。A.
斜纹菊科植物

感谢您的详细回答!我有一种预感,
doesNotWork2
因为你提到的原因失败了,我不知道
a…
家族。对于我的大多数用例,我可能不需要秩-2多态性,所以这是完美的!
worksEasily :: ( Member (Reader C) e ) => ALens' C B -> Eff e A
worksEasily bLens = do
  let compositeLens = bLens . a
  askLensed compositeLens
askLensed :: ( Member (Reader r) e ) => Getting a r a -> Eff e a
askLensed l = view l <$> ask

worksEasily :: ( Member (Reader r) e ) => Getting A r B -> Eff e A
worksEasily bLens = do
  let compositeLens = bLens . a
  askLensed compositeLens