将镜头传递给函数
Pass a lens into a function
我想根据记录中的特定值执行排序。因此,我正在考虑将镜头传递给 lensSort
函数,但我无法使其工作。
理想情况下我可以做这样的事情
lensSort :: HasLens a => Lens' a b -> a -> a -> -> Ordering
lensSort lens x y | x ^. lens > y ^. lens = GT
| x ^. lens < y ^. lens = LT
| otherwise = GT
并且可以用
之类的东西来调用它
data Rectangle = Rectangle { _height :: Int, _width :: Int }
makeLenses'' Rectangle
let foo = [Rectangle 1 2, Rectangle 2 1]
sortBy (lensSort height) foo
我没能让它发挥作用,担心我可能完全找错树了,我对 Haskell 还是个新手。
您可以实现您的 sortByLens
- 或者 sortByGetting
功能。从您的定义开始
{-# LANGUAGE TemplateHaskell #-}
module Test where
import Control.Lens
import Data.Function (on)
import Data.List (compare, sortBy)
data Rectangle = Rectangle { _height :: Int, _width :: Int }
$(makeLenses ''Rectangle)
我们将开始在 ghci 中创建您想要的函数:
stack ghci test.hs --package lens
> import Control.Lens
> import Data.Function
> import Data.List
> :t sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
> :t on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
> :t compare
compare :: Ord a => a -> a -> Ordering
将这些与您的方法结合起来
>:t sortBy (compare `on` (view height))
sortBy (compare `on` (view height)) :: [Rectangle] -> [Rectangle]
为了使这个更通用一些,我们执行以下操作
>:t \lens -> sortBy (compare `on` (view lens))
\lens -> sortBy (compare `on` (view lens)) :: Ord a => Getting a s a -> [s] -> [s]
所以我们可以定义
sortByGetting :: Ord a => Getting a s a -> [s] -> [s]
sortByGetting g = sortBy (compare `on` view g)
除了拼写错误外,您的代码实际上几乎可以正常工作——显然唯一需要的是 b
事实上具有可比性。以下作品:
{-# LANGUAGE TemplateHaskell, RankNTypes #-}
import Control.Lens
import Control.Lens.TH
import Data.List
data Rectangle = Rectangle { _height :: Int, _width :: Int }
deriving (Show)
makeLenses ''Rectangle
lensSort :: Ord b => Lens' a b -> a -> a -> Ordering
lensSort lens x y | x ^. lens > y ^. lens = GT
| x ^. lens < y ^. lens = LT
| otherwise = GT
foo :: [Rectangle]
foo = [Rectangle 1 2, Rectangle 2 1]
main = print $ sortBy (lensSort height) foo
-- [Rectangle {_height = 1, _width = 2},Rectangle {_height = 2, _width = 1}]
请注意,实际上并不需要传递一个实际的镜头,因为无论如何您只将它用作 getter(≅函数)。所以你可以做
import Data.Ord (comparing)
main = print $ sortBy (comparing (^.height))
...没有任何额外的定义。
我想根据记录中的特定值执行排序。因此,我正在考虑将镜头传递给 lensSort
函数,但我无法使其工作。
理想情况下我可以做这样的事情
lensSort :: HasLens a => Lens' a b -> a -> a -> -> Ordering
lensSort lens x y | x ^. lens > y ^. lens = GT
| x ^. lens < y ^. lens = LT
| otherwise = GT
并且可以用
之类的东西来调用它data Rectangle = Rectangle { _height :: Int, _width :: Int }
makeLenses'' Rectangle
let foo = [Rectangle 1 2, Rectangle 2 1]
sortBy (lensSort height) foo
我没能让它发挥作用,担心我可能完全找错树了,我对 Haskell 还是个新手。
您可以实现您的 sortByLens
- 或者 sortByGetting
功能。从您的定义开始
{-# LANGUAGE TemplateHaskell #-}
module Test where
import Control.Lens
import Data.Function (on)
import Data.List (compare, sortBy)
data Rectangle = Rectangle { _height :: Int, _width :: Int }
$(makeLenses ''Rectangle)
我们将开始在 ghci 中创建您想要的函数:
stack ghci test.hs --package lens
> import Control.Lens
> import Data.Function
> import Data.List
> :t sortBy
sortBy :: (a -> a -> Ordering) -> [a] -> [a]
> :t on
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
> :t compare
compare :: Ord a => a -> a -> Ordering
将这些与您的方法结合起来
>:t sortBy (compare `on` (view height))
sortBy (compare `on` (view height)) :: [Rectangle] -> [Rectangle]
为了使这个更通用一些,我们执行以下操作
>:t \lens -> sortBy (compare `on` (view lens))
\lens -> sortBy (compare `on` (view lens)) :: Ord a => Getting a s a -> [s] -> [s]
所以我们可以定义
sortByGetting :: Ord a => Getting a s a -> [s] -> [s]
sortByGetting g = sortBy (compare `on` view g)
除了拼写错误外,您的代码实际上几乎可以正常工作——显然唯一需要的是 b
事实上具有可比性。以下作品:
{-# LANGUAGE TemplateHaskell, RankNTypes #-}
import Control.Lens
import Control.Lens.TH
import Data.List
data Rectangle = Rectangle { _height :: Int, _width :: Int }
deriving (Show)
makeLenses ''Rectangle
lensSort :: Ord b => Lens' a b -> a -> a -> Ordering
lensSort lens x y | x ^. lens > y ^. lens = GT
| x ^. lens < y ^. lens = LT
| otherwise = GT
foo :: [Rectangle]
foo = [Rectangle 1 2, Rectangle 2 1]
main = print $ sortBy (lensSort height) foo
-- [Rectangle {_height = 1, _width = 2},Rectangle {_height = 2, _width = 1}]
请注意,实际上并不需要传递一个实际的镜头,因为无论如何您只将它用作 getter(≅函数)。所以你可以做
import Data.Ord (comparing)
main = print $ sortBy (comparing (^.height))
...没有任何额外的定义。