下面是一个可能很愚蠢的例子,但我认为解决这个问题将解决我的另一个问题,详细in this question。
我想用这个签名写一个函数:
myread :: (Read a) => String -> a
这样myread = read
,a ~ Int
除外,在这种情况下myread _ = 0
。
显然这个功能本身很傻,但关键是我想根据返回类型进行优化。
重写规则,或者这里的一切都没问题。对于我的实际问题,如果解决方案是重写规则,那么在没有触发的情况下并不重要,但我想要的答案是至少给出一个它的例子。
答案 0 :(得分:1)
如果您记得规则的左侧是表达式上下文,不>,您可以直接使用重写规则(可能)以明显的方式执行此操作em>在模式上下文中。特别是,左侧的类型应用程序是完全有效的。
{-# LANGUAGE TypeApplications #-}
module A where
{-# INLINE [1] myread #-}
{-# RULES "myread" forall s . myread @Int s = 0 #-}
myread :: Read a => String -> a
myread = read
即使没有类型应用程序,以下内容也完全有效(但可能不是一般的,例如,如果输出类型为f a
,并且您希望仅{{1}优化{{1} },你不能拥有f
):
.. = (result :: [ _ ])
作为一个例子,使用
{-# RULES "myread" forall s . myread s = (0 :: Int) #-}
规则触发的证据总是要看核心,当然(省略不相关的位):
module B where
import A
fun :: String -> String -> (Int, Bool)
fun x y = (myread x, myread y)
请注意,这只是一个评论,而不仅仅是因为我不确定目标是什么,但代码不适合评论。
答案 1 :(得分:0)
如何使用不可判定的实例定义新类?
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE UndecidableInstances #-}
class MyRead a where
myread :: String -> a
instance {-# OVERLAPPABLE #-} Read a => MyRead a where
myread = read
instance MyRead Int where
myread = const 0
main = do
print $ (myread "True" :: Bool) -- True
print $ (myread "\"string\"" :: String) -- "string"
print $ (myread "12" :: Int) -- 0