我正在开发一个将二进制格式解析为Haskell值的库。第一步创建一个ADT,它通过某些原始值提供额外的类型信息。我在下面写了一个简化版本Object
。
我希望该库的用户将此值视为Functor
,或者使用其他方法从结构中提取值。我无法为Functor
编写有效的Object
实例。是否可以这样做?
data Object a
= N
| B Bool
| I Int
| L [Object a]
deriving (Eq, Show)
instance Functor Object where
fmap f N = N
fmap f (B x) = B $ f x
-- etc.
-- GHC error.
-- % ghci Object.hs
-- GHCi, version 7.10.1: http://www.haskell.org/ghc/ :? for help
-- [1 of 1] Compiling Main ( Object.hs, interpreted )
-- Object.hs:10:22:
-- Couldn't match expected type ‘Bool’ with actual type ‘b’
-- ‘b’ is a rigid type variable bound by
-- the type signature for fmap :: (a -> b) -> Object a -> Object b
-- at Object.hs:9:3
-- Relevant bindings include
-- f :: a -> b (bound at Object.hs:10:8)
-- fmap :: (a -> b) -> Object a -> Object b (bound at Object.hs:9:3)
-- In the second argument of ‘($)’, namely ‘f x’
-- In the expression: B $ f x
-- Object.hs:10:24:
-- Couldn't match expected type ‘a’ with actual type ‘Bool’
-- ‘a’ is a rigid type variable bound by
-- the type signature for fmap :: (a -> b) -> Object a -> Object b
-- at Object.hs:9:3
-- Relevant bindings include
-- f :: a -> b (bound at Object.hs:10:8)
-- fmap :: (a -> b) -> Object a -> Object b (bound at Object.hs:9:3)
-- In the first argument of ‘f’, namely ‘x’
-- In the second argument of ‘($)’, namely ‘f x’
-- Failed, modules loaded: none.
-- Prelude>
答案 0 :(得分:1)
您可以使用
instance Functor Object where
fmap f N = N
fmap f (B x) = B x
fmap f (I i) = I i
fmap f (L xs) = L $ map (fmap f) xs
或者更简单地说:
data Object a
= N
| B Bool
| I Int
| L [Object a]
deriving (Eq, Show, Functor)
启用DeriveFunctor
扩展程序后。
请注意,您的a
未在任何地方使用,因此Object a
为幻像类型。这是故意的吗?
因此,您无法将f
真正应用于任何内容,因为您需要类型为a
的值。您正尝试将f
应用于Bool
的固定类型,但这不会进行类型检查,因为f
的类型为a -> b
,其中{{1}是a
中的a
,不一定是Object a
。