标签: haskell-lens

如何组合镜片和仿函数?

我正在尝试习惯lensHaskell 的库,发现自己在一些简单的问题上苦苦挣扎.例如,让我们说(为了方便起见)at并且_1具有以下类型(这至少是我理解它们的方式):

at :: Ord k => k -> Lens' (Map k v) (Maybe v)

_1 :: Lens' (a, b) a
Run Code Online (Sandbox Code Playgroud)

如何将这些镜头组合成以下类型的镜头:

maybeFst :: Ord k => k -> Lens' (Map k (a, b)) (Maybe a)
Run Code Online (Sandbox Code Playgroud)

haskell lenses haskell-lens

11
推荐指数
1
解决办法
186
查看次数

在Lens中有这样的捷径吗?

镜头库中是否有这样的快捷方式?

\x -> liftM (^. x) get
Run Code Online (Sandbox Code Playgroud)

也许这是一个愚蠢的问题,但它感觉就像一个基本的结构,应该有一个捷径.

haskell haskell-lens

11
推荐指数
1
解决办法
285
查看次数

Haskell,Lenses,Getters和Setters

我无法理解Haskell中镜头库的所有细微差别.

假设我有以下镜头

activePlayer :: Lens' Game Player
activePlayer = lens get set
    where
        get (Game {_players = (index, seq) }) = S.index seq index
        set g@(Game {_players = (index, seq) }) player =
            g { _players = (index, S.update index player seq) }
Run Code Online (Sandbox Code Playgroud)

在ghci提示符下执行以下操作没有问题:

> :t do{use (activePlayer); activePlayer.= undefined}
     :: Control.Monad.State.Class.MonadState Game m => m ()
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试将其参数化为函数时,我得到以下错误.

> :t \p -> do{use p; p.=undefined}
<interactive>:1:17:
    Couldn't match type `Accessor a0 a0' with `Mutator b0'
    Expected type: ASetter s0 s0 …
Run Code Online (Sandbox Code Playgroud)

haskell haskell-lens

10
推荐指数
1
解决办法
1394
查看次数

从镜头获取默认值的Maybe

许多镜头吸气剂返回Maybe值.我经常需要用默认值替换它们.

说地图查找,但默认.

fromMaybe "" $ Map.fromList [(1,"Foo")] ^? at 1
Run Code Online (Sandbox Code Playgroud)

这可以用镜头语法编写吗?也许接近这个:

Map.fromList [(1,"Foo")] ^? at 1.or ""
Run Code Online (Sandbox Code Playgroud)

haskell haskell-lens

10
推荐指数
1
解决办法
1110
查看次数

镜头和单态限制

我一直在研究本文中给出的用于创建镜头的示例.

Lens按照文章中的说明创建了以下代码:

{-# LANGUAGE TemplateHaskell #-}
import Control.Lens

type Degrees = Double
type Latitude = Degrees
type Longitude = Degrees

data Meetup = Meetup { _name :: String, _location :: (Latitude, Longitude) }
makeLenses ''Meetup

meetupLat = location._1 :: Lens' Meetup Latitude
Run Code Online (Sandbox Code Playgroud)

现在这个代码没有类型检查,除非我包含这个:

{-# LANGUAGE NoMonomorphismRestriction #-}
Run Code Online (Sandbox Code Playgroud)

但在文章中没有任何地方,我可以发现他们已经提到了单态限制.这是正常的事情还是我在这里做错了什么?

编译使用:GHC 7.6.2

haskell haskell-lens

10
推荐指数
1
解决办法
316
查看次数

如何在使用镜头访问不存在的字段时避免默认返回值?

我喜欢镜头库,我喜欢它的工作方式,但有时它引入了很多问题,我后悔自己开始使用它.让我们看看这个简单的例子:

{-# LANGUAGE TemplateHaskell #-}

import Control.Lens

data Data = A { _x :: String, _y :: String }
          | B { _x :: String }

makeLenses ''Data

main = do
    let b = B "x"    
    print $ view y b
Run Code Online (Sandbox Code Playgroud)

它输出:

""
Run Code Online (Sandbox Code Playgroud)

现在想象 - 我们有一个数据类型,我们通过改变一些名称来重构它.这个名称不再适用于特定的数据构造函数,而是获得错误(在运行时,与普通访问器一样),镜头使用memptyfrom Monoid来创建默认对象,因此我们得到奇怪的结果而不是错误.调试这样的东西几乎是不可能的.有没有办法解决这个问题?我知道有一些特殊的操作员可以获得我想要的行为,但是所有来自镜头的"正常"外观功能都非常糟糕.我应该用我的自定义模块覆盖它们还是有更好的方法?

作为旁注:我希望能够使用镜头语法读取和设置参数,但只删除字段缺失时自动结果创建的行为.

haskell haskell-lens

10
推荐指数
2
解决办法
307
查看次数

使用镜头的3种以上类型的同构

受到ADT之间多态函数问题的启发,我试图在多个(不仅仅是2个)类型之间创建同构,因此每次我需要一个同构但不是同一类型时,我可以将一些代码洒在我的代码上convert.

假设我有3个ADT:

data AB = A | B deriving (Show)
data CD = C | D deriving (Show)
data EF = E | F deriving (Show)
Run Code Online (Sandbox Code Playgroud)

使用lens我可以实现AB和CD,CD和EF之间的2个同构:

{-# LANGUAGE MultiParamTypeClasses #-}
class Isomorphic a b where
  convert :: Iso' a b

instance Isomorphic AB CD where
  convert = iso ab2cd cd2ab
    where ab2cd A = C
          ab2cd B = D
          cd2ab C = A
          cd2ab D = B

instance Isomorphic AB EF where
  convert …
Run Code Online (Sandbox Code Playgroud)

haskell type-conversion isomorphism haskell-lens

10
推荐指数
1
解决办法
209
查看次数

每个镜头都是一次穿越……怎么样?

Control.Lens.Tutorial说:

type Traversal' a b = forall f . Applicative f => (b -> f b) -> (a -> f a) 
type Lens'      a b = forall f . Functor     f => (b -> f b) -> (a -> f a) 
Run Code Online (Sandbox Code Playgroud)

请注意,Lens' 和 Traversal' 之间的唯一区别是类型类约束。“镜头”具有函子约束,“遍历”具有应用约束。这意味着任何 Lens' 也自动成为有效的 Traversal'(因为 Functor 是 Applicative 的超类)。

我只是不遵循这里的逻辑顺序。我们知道每个Applicative都是一个Functor。由此看来,如果有的话,难道不应该得出每个Traversal'都是 a 吗Lens'?然而,本教程得出了相反的结论。

haskell functor applicative haskell-lens

10
推荐指数
1
解决办法
647
查看次数

压缩遍历

我有一个Traversable漏洞 - 想象一下这个二叉树:

         /       \
       /    \     Nothing
 Just 1    /  \  
    Nothing   Just 3
Run Code Online (Sandbox Code Playgroud)

我还有一个值列表来填补 - [2, 4]- 导致:

         /       \
       /    \     Just 4
 Just 1    /  \  
     Just 2   Just 3
Run Code Online (Sandbox Code Playgroud)

我认为可以使用lens索引遍历遍历Nothings并用列表中相应索引处的值替换它们.

但是必须可以在不使用指数的情况下直接做更多的事情吗?

奖励积分 - 此主题的一些变化:

  1. (我的用例)值列表必须与遍历中的孔具有完全相同的元素数.失败表示一个Maybe.
  2. 名单必须有至少尽可能多的元素,所以我们也可以通过在[2, 4, 6],[2, 4, ..]等等.
  3. 列表可以包含任意数量的元素,并且我们可以使用我们给出的元素填充尽可能多的孔.此操作不会失败,它只能填充任意数量的孔.

haskell haskell-lens

9
推荐指数
2
解决办法
120
查看次数

遍历'过滤'的最后一个元素

我想过滤遍历,然后选择要使用的最后一个元素over.

像这样的东西(但实际上会编译):

[1,2,3,4] & traverse . filtered even . _last +~ 10
> [1,2,3,14]
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?

PS我知道filtered只有在不影响遍历中的元素数量时才有效.

我正在执行的实际用例是仅选择uniplate与某个谓词匹配的递归遍历的最低级别; 如果你对如何做到这一点有其他想法,我很乐意听到它们!

haskell haskell-lens

9
推荐指数
1
解决办法
175
查看次数