2017-10-16 10 views
3

レコード内の特定の値に基づいて並べ替えを実行したいと思います。そのような私は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 

ようなもので、それを呼び出すことができる可能性間違った木を完全に上に置いて、私はまだハスケルにとっては新しいです。

答えて

7

を定義することができ、それがあるとして、あなたのコードは、実際にはほとんどの作品 - 明らかに必要な唯一のものは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}] 

注あなただけとにかくゲッター(≅function)としてそれを使用しているため、実際のレンズの周囲を通過する必要が本当に存在していないこと。あなただけのことができます

import Data.Ord (comparing) 
main = print $ sortBy (comparing (^.height)) 

...余分な定義なし。

+0

'comparison'でこれを行うのは素晴らしいヒントです、ありがとう – eddiec

4

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) 
+1

また、['sortOn'](https://hackage.haskell.org/package/base-4.10.0.0/docs/Data-List.html#v:sortOn)を使うこともできます:' sortOnGetting g = sortOn (view g) ' – jpath

+0

@jpath thx - 何らかの理由で私はこの機能が存在することをいつも忘れています! – epsilonhalbe