2013-10-04 2 views
2

Рассмотрим следующий пример:Запись Упрощение шаблону внутри фильтра

data TestType = Free | Occupied { oc_field1 :: Int, 
            oc_field2 :: Int, 
            oc_field3 :: Int, 
            oc_field4 :: Int 
           } 

type SampleTest = [TestType] 

filterOccupied :: SampleTest -> SampleTest 
filterOccupied test = filter (\x -> case x of 
           Occupied _ _ _ _ -> True 
           Free -> False) test 

В приведенном выше примере, внутри filterOccupied я должен использовать четыре _ для согласования Occupied типа.

Это становится очень болезненным, когда в записях имеется более десяти полей. Есть лучший способ сделать это ?

ответ

5

Вместо этого вы можете использовать шаблон {}.

filterOccupied :: SampleTest -> SampleTest 
filterOccupied test = filter (\x -> case x of 
           Occupied {} -> True 
           Free -> False) test 
3

Добавление ответа Snak, это также может быть проще с пониманием списка:

filterOccupied :: SampleTest -> SampleTest 
filterOccupied test = [x | [email protected](Occupied {}) <- test] 

только те элементы, которые соответствуют шаблону, сохраняются в списке.

0

насчет:

data TestType = Free 
       | Occupied { oc_field1 :: Int 
         , oc_field2 :: Int 
         , oc_field3 :: Int 
         , oc_field4 :: Int 
         } 
    deriving Eq 

filterOccupied :: [TestType] -> [TestType] 
filterOccupied = filter (Free/=) 
+0

Мне не нравится использование тестов равенства, где вы могли бы использовать по шаблону вместо этого, поскольку он производит паразитные 'Eq' ограничение (это еще хуже с' (== []) ' , который вы видите в новом коде Haskellers, так как тогда * элементы * получают ограничение). Плюс это просто менее элегантно. Определение функций 'isFree' /' isOccupied' было бы моим предпочтительным подходом, если бы вы действительно хотели чего-то подобного. –

Смежные вопросы