C#:
static int F(object x)
{
return x is string ? 1 : 2;
}
Haskell? Хитрый бит кажется мне, что у Haskell нет корневого текстового объекта.
Отредактированный: Я не забочусь о преобразовании в строку. Я хочу знать, как преобразовать тип (например, чтобы видеть, является ли объект Клиентом или Порядком.
В Haskell все типы которые позволяют преобразование в строку, создают экземпляр класса типов Show
, который предоставляет
show :: Show a => a -> String
Таким образом, весь ваш код - это не что иное, как
f x = show x
или
f = show
с тем же универсальным типом f :: Show a = > a -> String
(Для всех типов a
, которые могут преобразовываться в строку, принимают значение этого типа и возвращают строку).
Обратите внимание, что вам не нужно выполнять явная проверка типа во время выполнения, как в C #; общий шаблон разрешается во время компиляции. Вам не нужен полиморфный корневой тип - приведение типов, как в C #, на самом деле было бы несколько сложным и противоречило бы концепции языка. Вместо того чтобы разрешать произвольное приведение типов между типами, он определил классы типов для определенных значимых преобразований.
Обратите внимание, что совместимость проверяется во время компиляции:
-- Working
f 1
f "Hallo"
f (1, 2)
f [1, 2, 3]
-- Not working
f (\x -> x + 1)
В ответ на ваш отредактированный вопрос :
Как я уже сказал ранее, произвольные преобразования не разрешены в Haskell (без очень небезопасного кода). А поскольку Haskell не является объектно-ориентированным, нет отношений наследования, требующих приведения типов. Просто не существует бессмысленных значений объекта
, которые требовали проверки / преобразования во время выполнения. Для выражения альтернатив вам нужно будет определить тип объединения, класс типов или использовать тип Either
.
В каком случае вы встретите объект, который является Customer
или Заказ
? Значение такого типа просто бессмысленно. Пожалуйста, уточните еще раз.
Вам понадобится класс типа:
class Loggable a where
writeToLog :: a -> IO ()
If you want to have objects that can either be Customers or Orders, then you'd introduce a new datatype "Customer|Order" so that each object carries a type tag saying which it is.
I don't know the Haskell syntax offhand, but in F# it would be
type CustOrOrd =
| Cust of Customer
| Ord of Order
let F (x:CustOrOrd) : int =
match x with
| Cust c -> 1
| Ord o -> 2
let thing1 = Cust someCustomer
let thing2 = Ord someOrder
// can call F on thing1 or thing2
More generally, in Haskell if you want to do something like a fixed OO type hierarchy (for a fixed set of highly related types, to be able to treat them as the same type in some cases), you may use a union type as above. On the other hand, for common operations across a variety of unrelated types (like ToString/Show) you might use a Haskell type class.
This is something I've tried before, and I don't think you can do it.
Introduction to Haskell Pure Functions
Haskell takes a very different approach. It starts by performing type analysis with a type checker to understand your program at compile time. The type checker strictly prohibits type casting and does not allow type errors to be ignored. Because types are checked at compile time, and there is no escape from the type checker, Haskell is frequently described as both statically typed and strongly typed.
Приведение и is
/ instanceof
имеют смысл в языках, в которых есть подтипы . На ваш вопрос можно ответить несколькими способами:
is
/ instanceof
не имеет смысла в Haskell; есть только явные преобразования. Не существует типа объекта
, от которого происходят все типы. show
- это перегруженное имя для преобразования любого типа в String. Классы типов также могут использоваться для того, чтобы некоторые преобразования (казались) неявными. Дарио прав, обычно в Haskell вы хотите создать класс типа для отправки по типу чего-то. При этом есть безопасный способ преобразования типов в Haskell. Это часть общей библиотеки программирования Scrap your template , которая позволяет вам писать "интересные" части манипуляций со сложными вложенными типами данных, в то время как SYB заполняет пробелы. Мозг невероятно крутой. Вот его презентация в ppt или html .
Вот как выглядит приведение:
cast :: (Typeable a, Typeable b) => a -> Maybe b
ghci> (cast 'a') :: Maybe Char
Just 'a'
ghci> (cast 'a') :: Maybe Bool
Nothing
ghci> (cast True) :: Maybe Bool
Just True
Самый простой способ - использовать Data.Typeable , как отмечает Дарио, который охватывает все стандартные типы, хотя вам необходимо передать " Deriving Typeable
"или иным образом реализовать typeOf
, чтобы охватить ваши собственные определения типов. Это не стандартный Haskell 98, но он находится в ghc начиная с 6.2.2.
Ваш код может быть реализован:
stringtyperep :: TypeRep stringtyperep = typeOf "somestring" F :: (Typeable 'a) =>'a -> Integer F x | (typeOf x == stringtyperep) = 1 F x = 2
В общем, отражение типов в стиле объектно-ориентированных приложений лучше выполнять с помощью универсального программирования, но это не будет хороший пример для этого.
Кроме того, все типы в классе типов Typeable
могут быть «преобразованы» в Data.Dynamic .
В C #, вероятно, более эффективно не выполнять приведение:
return x == null ? null : x.ToString();
В Haskell есть класс типа "show", все, что реализует класс типа, может вызывать вызов show, поэтому нет требуется кастинг.