Могу ли я сформировать сопоставление на имя типа? -- haskell пол Связанный проблема

Can I pattern match on type name?


1
vote

проблема

русский

Можно ли узозить совпадение на самом названии типа, а не на одном из конструкторов типа?

Вот надуманный пример с кодом, который не скомпилируется, который, я надеюсь, объясняет, что я после:

 <Код> what :: a -> String what (x :: String) = "It's a String!" what (x :: Int) = "It's an Int!" what x = "Not sure what it is."   
Английский оригинал

Is it possible to pattern match on the type name itself instead of on one of a type's constructors?

Here's a contrived example with code that doesn't compile which I hope explains what I'm after:

what :: a -> String what (x :: String) = "It's a String!" what (x :: Int) = "It's an Int!" what x = "Not sure what it is." 
</div
  
 
 

Список ответов

6
 
vote
vote
Лучший ответ
 

Вот версия с использованием классов типа:

 <код> {-# LANGUAGE TypeSynonymInstances, FlexibleInstances  #-} module Test where  class What a where   what :: a -> String  instance What String where   what _ = "It's a String!"  instance What Int where   what _ = "It's an Int"   

Пример:

 <код> λ> what "hi" "It's a String!" λ> what (1 :: Int) "It's an Int"   

И если вы хотите, чтобы Else :

 <код> {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverlappingInstances  #-} module Test where  class What a where   what :: a -> String  instance What String where   what _ = "It's a String!"  instance What Int where   what _ = "It's an Int"  instance What a where   what _ = "not sure"   

Пример:

 <код> curl -d '{"aps":{"alert":"This is a test notification"}}' --cert YourCertificate.pem:YourPassword -H "apns-topic: com.example.yourapp" --http2  https://api.development.push.apple.com/3/device/YourDeviceToken 0  
 

here is a version using type-classes:

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances  #-} module Test where  class What a where   what :: a -> String  instance What String where   what _ = "It's a String!"  instance What Int where   what _ = "It's an Int" 

example:

λ> what "hi" "It's a String!" λ> what (1 :: Int) "It's an Int" 

and if you want the else case:

{-# LANGUAGE TypeSynonymInstances, FlexibleInstances, OverlappingInstances  #-} module Test where  class What a where   what :: a -> String  instance What String where   what _ = "It's a String!"  instance What Int where   what _ = "It's an Int"  instance What a where   what _ = "not sure" 

example:

λ> what "hi" "It's a String!" λ> what (1 :: Int) "It's an Int" λ> what True "not sure" 
</div
 
 
       
       
5
 
vote

Предупреждение

Уведомление, что вы просите что-то неочищенно неидиоматично. Все, что вы на самом деле пытаетесь сделать, это, вероятно, не правильный способ сделать это!

Решение

Ваша подпись типа верхнего уровня говорит, что вы можете справиться с любым типом, что-либо так, и что просто не будет летать. Типы все теряются во время компиляции, поэтому вам нужно что-то, чтобы проинформировать код, какой тип был, что-то для принятия решения о разветвлении.

Есть несколько небольших классов, которые вы могли бы наклониться здесь. Один называется Typeable , класс для типов, которые имеют представление времени выполнения:

 <код> class Typeable (a :: k) where   Data.Typeable.Internal.typeRep# :: GHC.Prim.Proxy# a -> TypeRep   

Для того, чтобы использовать типируемый в вашем случае, вы добавляете ограничение в вашу переменную типа и используете <код> typeOf для приобретения представлений типа:

 <код> {-# LANGUAGE MultiWayIf #-} import Data.Typeable  what :: Typeable a => a -> String what x =     let ty = typeOf x     in if | ty == intTy -> "It's an Int!"           | ty == strTy -> "It's a String!"           | otherwise -> "Something else, namely: " ++ show ty   where   strTy = typeOf ""   intTy = typeOf (0 :: Int)   

Удажность работы:

 <код> *Main> what (1::Int) "It's an Int!" *Main> what "foo" "It's a String!" *Main> what 1.1 "Something else, namely: Double"   
 

Warning

Notice you are asking for something starkly non-idiomatic. Whatever you are actually trying to do, this is probably not the right way to do it!

Solution

Your top level type signature says you can handle any type what-so-ever and that just isn't going to fly. Types are all lost at compile time so you need something to inform the code what the type was, something to make your branching decision.

There are a few lesser-used classes you could lean on here. One is called Typeable, a class for types that have a run-time representation:

class Typeable (a :: k) where   Data.Typeable.Internal.typeRep# :: GHC.Prim.Proxy# a -> TypeRep 

In order to use typeable in your case you add the constraint to your type variable and use typeOf to acquire type representations:

{-# LANGUAGE MultiWayIf #-} import Data.Typeable  what :: Typeable a => a -> String what x =     let ty = typeOf x     in if | ty == intTy -> "It's an Int!"           | ty == strTy -> "It's a String!"           | otherwise -> "Something else, namely: " ++ show ty   where   strTy = typeOf ""   intTy = typeOf (0 :: Int) 

Yielding operation of:

*Main> what (1::Int) "It's an Int!" *Main> what "foo" "It's a String!" *Main> what 1.1 "Something else, namely: Double" 
</div
 
 
 
 
4
 
vote

Нет, это невозможно.

Единственный способ сделать разные вещи в зависимости от типа - использовать методы TypeClass, которые реализованы по-разному для каждого типа.

 

No, that's not possible.

The only way to do different things depending on the type is to use typeclass methods that are implemented differently for each type.

</div
 
 
3
 
vote

Как вы пытаетесь перегрузить функцию в Haskell. Посмотрите на этот пост, который объясняет метод с участием типовых опор, который делает это: Функция перегрузки подписи Haskell

 

In a way you're trying to overload a function in Haskell. Have a look at this post that explains a method involving typeclasses which does that: Overloading function signatures haskell

</div
 
 

Связанный проблема

3  Функциональные учебные проблемы  ( Functional learning woes ) 
Я начинающий к функциональным языкам, и я пытаюсь зацепить все это в Haskell. Вот быстроразъемная функция, которая находит все факторы номера: <код> factors...

1  Aeson: анализ вложенного объекта AS (карта String MyshinyType)  ( Aeson parse nested object as map string myshinytype ) 
У меня есть файл JSON-схемы с помощью поля «Свойства». <код> { ... "properties": { "id": { "description": "ID", "type": "int...

0  Аргумент функции, который трансформируется в монаде  ( Function argument which transforms in st monad ) 
Как я могу написать следующую функцию <код> tt , который имеет в данный момент ошибки: <код> t :: Int t = runST $ do ref <- newSTRef 10 readSTRef ref t...

2  Выпуск производительности на цепочке Коллац  ( Performance issue on collatz chain ) 
У меня есть рабочая программа для вычисления самой длинной цепочки Collatz в данном диапазоне (проект EULER N ° 14). Я думаю, что это работает правильно, но о...

15  Как вы используете типопливники в Haskell?  ( How do you use typeapplications in haskell ) 
с -XTypeApplications в GHC 8.0, вы явно указываете типы с <код> @ предшествующих аргументах функций. Какие типы это точно уточняют, особенно когда введен н...

8  Emacs: переопределение команды в Haskell-Mode (Haskell-Mode-Took)  ( Emacs redefining command in haskell mode haskell mode hook ) 
В Emacs в Haskell-режиме я хотел изменить команду . "C-X C-S" к . «C-X C-S», а затем «C-C C-L». Принимая кий от: haskell.org: emacs / keybindings и...

4  Простое объяснение операторов <$> и <*>  ( Simple explanation of and operators ) 
Я должен дать (простой) говорить о yesod. И да, .. Я никогда не или действительно редко использовал Haskell. Университет преподавателя ..... а. Так что я пр...

20  Как поднимается (в функциональном контексте программирования) относится к теории категории?  ( How does lifting in a functional programming context relate to category theory ) 
Смотреть на haskell Документация, подъем, кажется, в основном обобщение <код> filter%5Blogic%5D=and&filter%5Bfilters%5D%5B0%5D%5Bvalue%5D=CAR&filter%5Bfilte...

3  Haskell - заставить строгую оценку со странным, рекурсивный тип  ( Haskell forcing strict evaluation with a weird recursive type ) 
i Ранее задали вопрос о том, как заставить строгая оценка для создания тайм-аута. Используя <код> seq / <код> $! достаточно большую часть времени, а <код>...

35  Функция Haskell Состав  ( Haskell function composition ) 
Я читаю Это Учебник на Haskell. Они определяют функцию функции как следующее: <код> (.) :: (b->c) -> (a->b) -> (a->c) f . g ...

1  Как написать генератор Haskell QuickCheck для Data.meldableheap Очередь приоритета  ( How to write a haskell quickcheck generator for a data meldableheap priority que ) 
Как учебное упражнение, которое я хочу написать генератор <код> Data.MeldableHeap . Я счеркнул его после: https://gitorious.org/aocapq/aoCapq/ Source / 7F2...

1  Как пользоваться арбитрами аргументами объектива Makefields с различными типами в той же функции?  ( How to use an arbitrary makefields lens argument with different types in the sam ) 
Я использую makeFields от объектива для генерации полей, перегруженных для различных структур. Я хотел бы использовать эти поля в одном с несколькими струк...

2  Обобщение функции объединить набор производителей труб Haskell  ( Generalizing a function to merge a set of haskell pipes producers ) 
Я работаю с Пакет Haskell Трубы . Я пытаюсь использовать Трубы-параллелизм для объединения списка производителей вместе. Что я хочу прибыть на: <код>...

4  Haskell Aeson Разрушение общих разбросов  ( Haskell aeson destructuring generic parse ) 
У меня есть запрос JSON в стиле <код> {"command":"get","params":{"something":"something else"}} и этот код фрагмента из yesod book <код> {-# LANGUAG...

2  Рассуждение о функциях, осматривая их тип подписи [закрыто]  ( Reasoning about functions by examining their type signatures ) 
<в сторону CLASS = "S-NEWACTS S-WELTIVE__info JS-Post-New Imide MB16« Роль = «Статус»> закрыт . Этот вопрос должен быть больше Фокусированный . В настоя...

Связанный проблема

3  Функциональные учебные проблемы 
1  Aeson: анализ вложенного объекта AS (карта String MyshinyType) 
0  Аргумент функции, который трансформируется в монаде 
2  Выпуск производительности на цепочке Коллац 
15  Как вы используете типопливники в Haskell? 
8  Emacs: переопределение команды в Haskell-Mode (Haskell-Mode-Took) 
4  Простое объяснение операторов <$> и <*> 
20  Как поднимается (в функциональном контексте программирования) относится к теории категории? 
3  Haskell - заставить строгую оценку со странным, рекурсивный тип 
35  Функция Haskell Состав 
1  Как написать генератор Haskell QuickCheck для Data.meldableheap Очередь приоритета 
1  Как пользоваться арбитрами аргументами объектива Makefields с различными типами в той же функции? 
2  Обобщение функции объединить набор производителей труб Haskell 
4  Haskell Aeson Разрушение общих разбросов 
2  Рассуждение о функциях, осматривая их тип подписи [закрыто]