gpt4 book ai didi

haskell - 类型级别文字 - 不能在二元函数中使用不同类型的参数

转载 作者:行者123 更新时间:2023-12-03 14:23:39 27 4
gpt4 key购买 nike

一起玩 Type Level Literals作为使用 Maybe 类型区分非空容器值(如幻像类型)的一种方式。

这很好用。 (需要 GHC >= 7.6.1)

但是试图定义一个二元函数(eq)

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym :: Symbol) a -> Bool

允许不同组的值,在使用时发出编译错误信号:

无法匹配类型 "Just"' with “没有”'
{-# LANGUAGE DataKinds, KindSignatures, GADTs, FlexibleInstances #-} 

import GHC.TypeLits

data TMaybe :: Symbol -> * -> * where
TNothing :: TMaybe "Nothing" a
TJust :: a -> TMaybe "Just" a

nonEmpty :: Maybe a -> TMaybe "Just" a
nonEmpty (Just x) = TJust x
nonEmpty Nothing = error "invalid nonEmpty data"

-- this fromJust rejects TNothing at compile time
fromJust :: (sym ~ "Just") => TMaybe (sym :: Symbol) a -> a
fromJust (TJust x) = x

tmbToMaybe :: TMaybe (sym :: Symbol) a -> Maybe a
tmbToMaybe TNothing = Nothing
tmbToMaybe (TJust x) = Just x

mbToTNothing Nothing = TNothing

mbToTJust (Just x) = TJust x

instance Eq a => Eq (TMaybe (sym :: Symbol) a) where
TNothing == TNothing = True
TJust x == TJust y = x == y
_ == _ = False -- useless, equal types required

instance Ord a => Ord (TMaybe (sym :: Symbol) a) where
compare TNothing TNothing = EQ
compare (TJust x) (TJust y) = Prelude.compare x y
compare TNothing _ = LT -- useless, equal types required
compare _ TNothing = GT -- useless, equal types required

instance Functor (TMaybe (sym :: Symbol)) where
fmap _ TNothing = TNothing
fmap f (TJust a) = TJust (f a)

instance Monad (TMaybe "Just") where
(TJust x) >>= k = k x

(TJust _) >> k = k

return = TJust
fail _ = error "can't fail to TNothing"

--------------------------

-- defining eq to admit parameter types with different symbol

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym :: Symbol) a -> Bool
eq TNothing TNothing = True
eq (TJust x) (TJust y) = x == y
eq _ _ = False

---------------------------

-- Test

main = do
print $ fromJust $ TJust (5::Int) -- type-checks
-- print $ fromJust TNothing -- as expected, does not type-check

-- print $ TNothing == TJust (5::Int) -- as expected, does not type-check, types required equal at function def.
print $ TNothing `eq` TJust (5::Int) -- does not type-check either

最佳答案

嗯,你的类型

eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym :: Symbol) a -> Bool

要求两个参数具有相同的类型,因此编译器当然会拒绝比较 TMaybe "Nothing" a 的尝试。和一个 TMaybe "Just" a .

如果您将类型更改为
eq :: (Eq a) => TMaybe (sym :: Symbol) a -> TMaybe (sym1 :: Symbol) a -> Bool

它编译和
TNothing `eq` TJust (5::Int)

计算结果为 False . (不过,您需要在许多地方明确确定 TNothing 的类型。)

关于haskell - 类型级别文字 - 不能在二元函数中使用不同类型的参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14753252/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com