Bob*_*Bob 0 haskell types type-inference church-encoding
以下代码旨在将布尔型的Church编码打印为Haskell的Bool:
{-#LANGUAGE FlexibleInstances #-}
instance Show (t -> t -> t) where
show b = show $ b True False
Run Code Online (Sandbox Code Playgroud)
导致此错误:
<interactive>:4:21: error:
• Couldn't match expected type ‘t’ with actual type ‘Bool’
‘t’ is a rigid type variable bound by
the instance declaration at <interactive>:3:10-27
• In the first argument of ‘b’, namely ‘True’
In the second argument of ‘($)’, namely ‘b True False’
In the expression: show $ b True False
• Relevant bindings include
b :: t -> t -> t (bound at <interactive>:4:8)
show :: (t -> t -> t) -> String (bound at <interactive>:4:3)
Run Code Online (Sandbox Code Playgroud)
如何使其运作?
问题是,show :: (t -> t -> t) -> String应该对工作的任何关于工作功能的任何类型t。您假设t这是非法的布尔值,因为(根据GHC)“ t是刚性类型变量”并且无法与专用类型统一。
一种可能的解决方案是通过Bool(FlexibleInstances必要)来专门化您的实例
{-#LANGUAGE FlexibleInstances #-}
instance Show (Bool -> Bool -> Bool) where
show b = show $ b True False
Run Code Online (Sandbox Code Playgroud)
但这会降低您的教堂布尔值的通用性。
不可能定义适用于任何类型的灵活解决方案,因为您将需要具有该类型的两个代表来描述正确和错误的情况,并且类似Void这样的类型都没有(定义的)值。
我想到的一个非常普遍的想法是在以下方面添加更多的类约束t:
{-#LANGUAGE FlexibleInstances #-}
import Data.Boolean
instance (Show t, Boolean t) => Show (t -> t -> t) where
show b = show $ b true false
Run Code Online (Sandbox Code Playgroud)
的Boolean类收集,可以被理解为在一些术语的逻辑值的类型。例如Bool:
instance Boolean Bool where
true = True
false = False
notB = not
(||*) = (||)
(&&*) = (&&)
Run Code Online (Sandbox Code Playgroud)
现在我们可以确保
t 你实际上可以做的一件事 showt显示为true和false实际能够以show这种方式起作用的签名所需的条件是哪些。
重要
以下示例不起作用:
show (true :: (Show t, Boolean t) => t -> t -> t)
Run Code Online (Sandbox Code Playgroud)
问题是typechecker不会猜测t您将在这里拥有哪个。该解决方案提供了有效且有效的实例,但仅适用于完全实例化的类型。如果出现歧义错误,则需要指定以下内容t:
show (true :: Bool -> Bool -> Bool)
>>> "True"
show (true :: Int -> Int -> Int) -- assuming Boolean instance
>>> "1"
Run Code Online (Sandbox Code Playgroud)
编辑:
评论中提到了另一个想法。解决方案是将您的布尔布尔值包装为Rank2Type:
{-# LANGUAGE Rank2Types #-}
newtype ChBool = ChBool (forall t. t -> t -> t)
Run Code Online (Sandbox Code Playgroud)
它将t是任何独立于上下文的类型。然后,您可以这样定义临时实例:
instance Show ChBool where
show (ChBool f) = show $ f True False
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
114 次 |
| 最近记录: |