#haskell #syntax #types #dynamic-typing
#haskell #синтаксис #типы #динамическая типизация
Вопрос:
Предположим, например, что у нас есть следующая структура данных:
data Foo = Bool Bool | Int Int | Double Double
Итак, есть ли более простой способ сделать это:
foo :: Typeable a => a -> Foo
foo x = maybe (error "i dunno") id $
liftM Bool (cast x) `mplus`
liftM Int (cast x) `mplus`
liftM Double (cast x)
Кто-нибудь думал о создании синтаксиса для сопоставления с образцом для типизируемых типов?
Ответ №1:
Используйте typeOf
и охраняет:
foo x
| tx == typeOf "str" = "string"
| tx == typeOf True = "bool"
| otherwise = "i dunno"
where tx = typeOf x
Комментарии:
1. Я думаю, что это хороший подход. Один незначительный момент заключается в том, что typeOf «str» не будет хорошо работать при наличии перегруженных строк, что в наши дни становится все более распространенным явлением.
2. Аналогичная проблема возникает с числовыми литералами. Это также не масштабируется до ситуаций, когда у вас нет конструкторов для типа данных / они не являются чистыми. В конечном итоге вы получили бы
(undefined :: Foo)
слишком долго, что уродливо. Из-за этого мне не нравится это решение.3. Набор типов должен быть немного уродливым. Это напоминает нам вернуться к программированию с реальными типами и прекратить возиться со всей этой мешаниной во время выполнения.
Ответ №2:
Вы можете использовать шаблоны просмотра здесь, они являются довольно удобным расширением.
{-# LANGUAGE ViewPatterns #-}
import Data.Data
data Foo = Bool Bool | Int Int | Double Double
deriving (Show)
foo :: Typeable a => a -> Foo
foo (cast -> Just x) = Int x
foo (cast -> Just x) = Bool x
foo (cast -> Just x) = Double x
foo _ = error "i dunno"
Результаты:
*Главная> :l foo_typeable.hs [1 из 1] Компиляция Main ( foo_typeable.hs, интерпретируется) Хорошо, загруженные модули: Main. *Main> foo "123" *** Исключение: я не знаю *Главная> foo 1 *** Исключение: я не знаю *Main> foo (1 :: Int) Int 1 *Main> foo (1 :: Целое число) *** Исключение: я не знаю *Main> foo (1 :: Double) Double 1.0
Комментарии:
1. Это довольно изящное решение!
Ответ №3:
Эта версия не ограничивается Bool
, Int
или Double
, но String
выходит как [Char]
.
foo :: Typeable a => a -> String
foo = show . typeOf
Комментарии:
1. … что разумно, поскольку
String
это просто псевдоним типа для[Char]
.