自然语言类型的子类型

use*_*580 6 haskell

我是一名致力于自然语言的正式语法/语义的语言学家.我最近才开始使用Haskell,很快我意识到我需要添加子类型.例如,考虑到人类和动物的类型,我想将Human作为Animal的子类型.我发现这可以使用强制函数,其中实例由用户声明,但我不知道如何在我感兴趣的实例中定义强制.所以基本上我不知道在'coerce =之后要添加什么'让它发挥作用'.这是到目前为止的代码:

{-# OPTIONS

 -XMultiParamTypeClasses
 -XFlexibleInstances
-XFunctionalDependencies
-XRankNTypes
-XTypeSynonymInstances 
-XTypeOperators
#-}

module Model where 

import Data.List



data Animal = A|B deriving (Eq,Show,Bounded,Enum)

data Man = C|D|E|K deriving (Eq,Show,Bounded,Enum)

class Subtype a b where
coerce :: a->b

instance Subtype Man Animal where
coerce=




animal:: [Animal]
animal = [minBound..maxBound] 

man:: [Man]
man = [minBound..maxBound]
Run Code Online (Sandbox Code Playgroud)

提前致谢

Gab*_*lez 12

只需忽略Subtype类一秒钟,然后检查您正在编写的强制函数的类型.如果aManbAnimal,那么你正在写应该是要挟函数的类型:

coerce :: Man -> Animal
Run Code Online (Sandbox Code Playgroud)

这意味着您所要做的就是编写一个合理的函数,将每个Man构造函数(即C | D | E | K)转换为相应的Animal构造函数(即A | B).这就是对子类型的意义,您可以在其中定义一些将"子"类型映射到原始类型的函数.

当然,您可以想象,因为您的Man类型有四个构造函数,而您的类型只有两个构造函数,所以Animal最终会有多个Man构造函数映射到同一个Animal构造函数.这并没有错,它只是意味着强制功能是不可逆的.如果不确切知道那些构造函数应该代表什么,我就无法对此发表更多评论.

对你的问题更一般的答案是,没有办法自动知道哪些构造函数Man应该映射到哪个构造函数Animal.这就是为什么你必须写出强制函数来告诉它人与动物之间的关系是什么.

另请注意,'Subtype'类和'coerce'函数没有什么特别之处.你可以跳过它们并编写一个'manToAnimal'函数.毕竟没有内置语言或编译器支持子类型,而Subtype只是一个随机人提出的另一个类(坦率地说,子类型不是真正的惯用Haskell,但你并没有真正问过这个) .定义类实例的所有操作都允许您重载函数coerce以处理Man类型.

我希望有所帮助.


luq*_*qui 8

你在"需要添加子类型"的地方工作的抽象级别是多少?

  1. 您是否正在尝试为由Haskell类型编码的程序创建世界模型?(如果您的类型实际上是 Animal,我可以看到这个Dog,等等)
  2. 您是否正在尝试创建更多通用软件,并且您认为子类型将是一个好的设计?
  3. 或者你只是在学习哈斯克尔并玩弄东西.

如果(1),我认为这对你来说不会那么好.Haskell没有很好的反射能力 - 即将类型逻辑编织到运行时逻辑中的能力.你的模型最终会与实现完全纠缠在一起.我建议创建一个"世界模型"(一组)类型,而不是一组与特定世界模型相对应的类型.即,为Haskell回答这个问题:什么是世界模型?

如果(2),再想一想:-).子类型是Haskell不参与的设计传统的一部分.还有其他方法可以设计你的程序,它们最终会在功能性思维模式中发挥更好的作用,然后进行子类型化.开发您的功能设计意识需要时间,因此请耐心等待.记住:保持简单,愚蠢.使用数据类型和函数(但请记住使用高阶函数来概括和共享代码).如果你正在寻求高级功能(即使类型词在我的意思上是相当先进的),你可能做错了.

如果(3),请看Doug的答案,并玩弄东西.有很多方法可以伪造它,最终它们都很糟糕.


Dou*_*ore 5

我对自然语言知之甚少,所以我的建议可能会忽略这一点,但这可能就是你要找的东西.

{-# OPTIONS
  -XMultiParamTypeClasses
  -XFlexibleContexts
#-}
module Main where

data Animal = Mammal | Reptile deriving (Eq, Show)
data Dog = Terrier | Hound deriving (Eq, Show)
data Snake = Cobra | Rattle deriving (Eq, Show)

class Subtype a b where
  coerce :: a -> b

instance Subtype Animal Animal where
  coerce = id

instance Subtype Dog Animal where
  coerce _ = Mammal

instance Subtype Snake Animal where
  coerce _ = Reptile

isWarmBlooded :: (Subtype a Animal) => a -> Bool
isWarmBlooded = (Mammal == ) . coerce

main = do
  print $ isWarmBlooded Hound
  print $ isWarmBlooded Cobra
  print $ isWarmBlooded Mammal
Run Code Online (Sandbox Code Playgroud)

给你:

True
False
True
Run Code Online (Sandbox Code Playgroud)

那是你拍摄的那种吗?Haskell没有内置的子类型,但这可能是一种解决方法.诚然,可能有更好的方法来做到这一点.

注意:此答案并非旨在指出解决手头问题的最佳,正确或自觉的方法.它旨在回答这个问题,即"在'coerce ='之后添加什么才能让它发挥作用."


ehi*_*ird 4

coerce你至少不能编写你正在寻找的函数 \xe2\x80\x94 ,这是不明智的。中没有任何值Animal与 中的值相对应Man,因此您无法为 编写定义coerce

\n\n

由于各种原因,Haskell 没有将子类型作为显式设计决策(它允许类型推断更好地工作,并且允许子类型使语言的类型系统变得非常复杂)。相反,您应该使用聚合来表达这样的关系

\n\n
data Animal = A | B | AnimalMan Man deriving (Eq, Show, Bounded, Enum)\ndata Man = C | D | E | K deriving (Eq, Show, Bounded, Enum)\n
Run Code Online (Sandbox Code Playgroud)\n\n

AnimalMan现在有了 type Man -> Animal,正是您想要coerce的。

\n