Для этого требуются зависимые типы - без этого не обойтись. В Idris, языке с зависимой типизацией, похожем на Haskell, вы можете написать это просто отлично:
data D : Bool -> Type where
D1 : D True
D2 : D False
-- The `{ .. }` mean the argument is inferred.
x : {a : Bool} -> D a
x {a = True} = D1
x {a = False} = D2
В Haskell единственный способ диспетчеризации на основе типа во время выполнения — через классы типов, поэтому вам необходимо ограничение. На самом деле, как указывает @András, существует SingI
, который создан для этого (он взят из пакета singletons
, который работает именно с такой проблемой).
В вашем случае это будет:
{-# LANGUAGE GADTs, TypeInType, ScopedTypeVariables #-}
import Data.Singletons.Prelude
data D (a :: Bool) where
D1 :: D True
D2 :: D False
x :: forall a. SingI a => D a
x = case sing :: Sing a of
STrue -> D1
SFalse -> D2
Возможно, стоит упомянуть, что, несмотря на наличие ограничения SingI
, для него уже определены все соответствующие экземпляры. Все остальное, что является допустимым типом D
, но не с аргументом Bool
(например, D Any
), терпит неудачу во время компиляции (экземпляр SingI
просто не найден).
ghci> let _ = x :: D True
ghci> let _ = x :: D False
ghci> let _ = x :: D Any
<interactive> error:
• No instance for (SingI Any) arising from a use of ‘x’
• In the expression: x :: D Any
In a pattern binding: _ = x :: D Any
person
Alec
schedule
22.01.2017
D a
, если только оно не нижнее. Если/когда мы получимpi
типов (нестертые типы), то можно будет писатьx :: pi a. D a
- person chi   schedule 22.01.2017D Any
является допустимым типом.DataKinds
по-прежнему допускает неопределенность уровня типа... - person Alec   schedule 22.01.2017x :: D True
иx :: D False
. - person Clinton   schedule 22.01.2017a :: Bool
может быть толькоTrue
илиFalse
. Диспетчеризация наa :: Bool
невозможна никак, так как стирается во время выполнения. Вам нужно как минимумx :: SingI a => D a
илиx :: Sing a -> D a
, если вы хотите отправить. - person András Kovács   schedule 22.01.2017a
стирается во время выполнения, как работает диспетчеризация для методов класса? Или тип сохраняется для типов с ограничениями класса? - person Clinton   schedule 22.01.2017Show a => a -> IO ()
это более или менее реализовано как(a -> String) -> a -> IO ()
. Фактические реализации методов класса передаются в качестве аргументов, поэтому типы не должны этого делать. - person Justin L.   schedule 22.01.2017