如何避免非预测式多态和定义镜头的镜头

3

我正在尝试为具有lens字段的数据类型生成lens。

data St st l = St {
  _st_s :: String,
  _st_lens :: Lens' st l
}

st_lens :: forall st l. Lens' (St st l) (Lens' st l)
st_lens = lens _st_lens (\s a -> s { _st_lens = a })

GHC 8.10.7 给我报错:

Illegal polymorphic type:
    forall (f1 :: * -> *). Functor f1 => (l -> f1 l) -> st -> f1 st
  GHC doesn't yet support impredicative polymorphism
• In the expansion of type synonym ‘Lens
2个回答

3

如果您使用的是GHC 9.2或更高版本,您可以打开ImpredicativeTypes,如Iceland_jack的回答所示。如果您现在无法切换到GHC版本,则一个预9.2的替代方案是将您的镜头存储为ALens,然后使用cloneLens适应的组合器之一来利用它:

data St st l = St {
  _st_s :: String,
  _st_lens :: ALens' st l
}

st_lens :: forall st l. Lens' (St st l) (ALens' st l)
st_lens = lens _st_lens (\s a -> s { _st_lens = a })

ghci> ("foo", 15) ^# (St "bar" _1 ^. st_lens)
"foo"
ghci> ("foo", 15) ^. cloneLens (St "bar" _1 ^. st_lens)
"foo"

3
{-# Language ImpredicativeTypes #-}
{-# Language TypeApplications #-}
-- ..

st_lens :: forall st l. Lens' (St st l) (Lens' st l)
st_lens = lens @_ @(Lens' st l) _st_lens \s a -> s { _st_lens = a }

2
即使我也打开了BlockArgumentsScopedTypeVariables,在GHC 8.10中这对我不起作用。错误是Couldn't match expected type ‘(l -> f1 l) -> st -> f1 st’ with actual type ‘Lens' st l’。它在9.2中运行良好,但如果您只启用ImpredicativeTypes而不需要任何类型应用程序,则提问者的原始代码也可以正常工作。 - Joseph Sible-Reinstate Monica

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接